Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/**
2
 * TinyMCE version 6.8.3 (2024-02-08)
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: ' + 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$3 = 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$2 = 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$5 = (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$5,
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$4 = (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$4(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$4(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$3 = (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$3 };
956
 
957
    const mediaMatch = query => window.matchMedia(query).matches;
958
    let platform$4 = cached(() => PlatformDetection.detect(navigator.userAgent, Optional.from(navigator.userAgentData), mediaMatch));
959
    const detect$2 = () => platform$4();
960
 
961
    const userAgent = navigator.userAgent;
962
    const platform$3 = detect$2();
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;
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$b = 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$3 = (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$a = (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$3(element, attr, nu.join(' '));
1219
      return true;
1220
    };
1221
    const remove$9 = (element, attr, id) => {
1222
      const nu = filter$5(read$4(element, attr), v => v !== id);
1223
      if (nu.length > 0) {
1224
        set$3(element, attr, nu.join(' '));
1225
      } else {
1226
        remove$a(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$8 = (element, clazz) => remove$9(element, 'class', clazz);
1235
    const toggle$2 = (element, clazz) => {
1236
      if (contains$2(get$8(element), clazz)) {
1237
        return remove$8(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$a(element, 'class');
1254
      }
1255
    };
1256
    const remove$7 = (element, clazz) => {
1257
      if (supports(element)) {
1258
        const classList = element.dom.classList;
1259
        classList.remove(clazz);
1260
      } else {
1261
        remove$8(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
    const hasChildNodes = element => element.dom.hasChildNodes();
1396
 
1397
    const getHead = doc => {
1398
      const b = doc.dom.head;
1399
      if (b === null || b === undefined) {
1400
        throw new Error('Head is not available yet');
1401
      }
1402
      return SugarElement.fromDom(b);
1403
    };
1404
 
1405
    const isShadowRoot = dos => isDocumentFragment$1(dos) && isNonNullable(dos.dom.host);
1406
    const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
1407
    const isSupported$1 = constant(supported);
1408
    const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
1409
    const getStyleContainer = dos => isShadowRoot(dos) ? dos : getHead(documentOrOwner(dos));
1410
    const getContentContainer = dos => isShadowRoot(dos) ? dos : SugarElement.fromDom(documentOrOwner(dos).dom.body);
1411
    const getShadowRoot = e => {
1412
      const r = getRootNode(e);
1413
      return isShadowRoot(r) ? Optional.some(r) : Optional.none();
1414
    };
1415
    const getShadowHost = e => SugarElement.fromDom(e.dom.host);
1416
    const getOriginalEventTarget = event => {
1417
      if (isSupported$1() && isNonNullable(event.target)) {
1418
        const el = SugarElement.fromDom(event.target);
1419
        if (isElement$7(el) && isOpenShadowHost(el)) {
1420
          if (event.composed && event.composedPath) {
1421
            const composedPath = event.composedPath();
1422
            if (composedPath) {
1423
              return head(composedPath);
1424
            }
1425
          }
1426
        }
1427
      }
1428
      return Optional.from(event.target);
1429
    };
1430
    const isOpenShadowHost = element => isNonNullable(element.dom.shadowRoot);
1431
 
1432
    const inBody = element => {
1433
      const dom = isText$b(element) ? element.dom.parentNode : element.dom;
1434
      if (dom === undefined || dom === null || dom.ownerDocument === null) {
1435
        return false;
1436
      }
1437
      const doc = dom.ownerDocument;
1438
      return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
1439
    };
1440
 
1441
    var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
1442
      if (is(scope, a)) {
1443
        return Optional.some(scope);
1444
      } else if (isFunction(isRoot) && isRoot(scope)) {
1445
        return Optional.none();
1446
      } else {
1447
        return ancestor(scope, a, isRoot);
1448
      }
1449
    };
1450
 
1451
    const ancestor$4 = (scope, predicate, isRoot) => {
1452
      let element = scope.dom;
1453
      const stop = isFunction(isRoot) ? isRoot : never;
1454
      while (element.parentNode) {
1455
        element = element.parentNode;
1456
        const el = SugarElement.fromDom(element);
1457
        if (predicate(el)) {
1458
          return Optional.some(el);
1459
        } else if (stop(el)) {
1460
          break;
1461
        }
1462
      }
1463
      return Optional.none();
1464
    };
1465
    const closest$4 = (scope, predicate, isRoot) => {
1466
      const is = (s, test) => test(s);
1467
      return ClosestOrAncestor(is, ancestor$4, scope, predicate, isRoot);
1468
    };
1469
    const sibling$1 = (scope, predicate) => {
1470
      const element = scope.dom;
1471
      if (!element.parentNode) {
1472
        return Optional.none();
1473
      }
1474
      return child(SugarElement.fromDom(element.parentNode), x => !eq(scope, x) && predicate(x));
1475
    };
1476
    const child = (scope, predicate) => {
1477
      const pred = node => predicate(SugarElement.fromDom(node));
1478
      const result = find$2(scope.dom.childNodes, pred);
1479
      return result.map(SugarElement.fromDom);
1480
    };
1481
    const descendant$2 = (scope, predicate) => {
1482
      const descend = node => {
1483
        for (let i = 0; i < node.childNodes.length; i++) {
1484
          const child = SugarElement.fromDom(node.childNodes[i]);
1485
          if (predicate(child)) {
1486
            return Optional.some(child);
1487
          }
1488
          const res = descend(node.childNodes[i]);
1489
          if (res.isSome()) {
1490
            return res;
1491
          }
1492
        }
1493
        return Optional.none();
1494
      };
1495
      return descend(scope.dom);
1496
    };
1497
 
1498
    const ancestor$3 = (scope, selector, isRoot) => ancestor$4(scope, e => is$1(e, selector), isRoot);
1499
    const descendant$1 = (scope, selector) => one(selector, scope);
1500
    const closest$3 = (scope, selector, isRoot) => {
1501
      const is = (element, selector) => is$1(element, selector);
1502
      return ClosestOrAncestor(is, ancestor$3, scope, selector, isRoot);
1503
    };
1504
 
1505
    const closest$2 = target => closest$3(target, '[contenteditable]');
1506
    const isEditable$2 = (element, assumeEditable = false) => {
1507
      if (inBody(element)) {
1508
        return element.dom.isContentEditable;
1509
      } else {
1510
        return closest$2(element).fold(constant(assumeEditable), editable => getRaw$1(editable) === 'true');
1511
      }
1512
    };
1513
    const getRaw$1 = element => element.dom.contentEditable;
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$6 = (element, property) => {
1565
      const dom = element.dom;
1566
      internalRemove(dom, property);
1567
      if (is$2(getOpt(element, 'style').map(trim$4), '')) {
1568
        remove$a(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$5(rogue);
1622
      });
1623
    };
1624
    const remove$5 = 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$5(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$2().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$2().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, selector, isRoot) => ancestor$3(scope, selector, isRoot).isSome();
1807
 
1808
    class DomTreeWalker {
1809
      constructor(startNode, rootNode) {
1810
        this.node = startNode;
1811
        this.rootNode = rootNode;
1812
        this.current = this.current.bind(this);
1813
        this.next = this.next.bind(this);
1814
        this.prev = this.prev.bind(this);
1815
        this.prev2 = this.prev2.bind(this);
1816
      }
1817
      current() {
1818
        return this.node;
1819
      }
1820
      next(shallow) {
1821
        this.node = this.findSibling(this.node, 'firstChild', 'nextSibling', shallow);
1822
        return this.node;
1823
      }
1824
      prev(shallow) {
1825
        this.node = this.findSibling(this.node, 'lastChild', 'previousSibling', shallow);
1826
        return this.node;
1827
      }
1828
      prev2(shallow) {
1829
        this.node = this.findPreviousNode(this.node, shallow);
1830
        return this.node;
1831
      }
1832
      findSibling(node, startName, siblingName, shallow) {
1833
        if (node) {
1834
          if (!shallow && node[startName]) {
1835
            return node[startName];
1836
          }
1837
          if (node !== this.rootNode) {
1838
            let sibling = node[siblingName];
1839
            if (sibling) {
1840
              return sibling;
1841
            }
1842
            for (let parent = node.parentNode; parent && parent !== this.rootNode; parent = parent.parentNode) {
1843
              sibling = parent[siblingName];
1844
              if (sibling) {
1845
                return sibling;
1846
              }
1847
            }
1848
          }
1849
        }
1850
        return undefined;
1851
      }
1852
      findPreviousNode(node, shallow) {
1853
        if (node) {
1854
          const sibling = node.previousSibling;
1855
          if (this.rootNode && sibling === this.rootNode) {
1856
            return;
1857
          }
1858
          if (sibling) {
1859
            if (!shallow) {
1860
              for (let child = sibling.lastChild; child; child = child.lastChild) {
1861
                if (!child.lastChild) {
1862
                  return child;
1863
                }
1864
              }
1865
            }
1866
            return sibling;
1867
          }
1868
          const parent = node.parentNode;
1869
          if (parent && parent !== this.rootNode) {
1870
            return parent;
1871
          }
1872
        }
1873
        return undefined;
1874
      }
1875
    }
1876
 
1877
    const isNodeType = type => {
1878
      return node => {
1879
        return !!node && node.nodeType === type;
1880
      };
1881
    };
1882
    const isRestrictedNode = node => !!node && !Object.getPrototypeOf(node);
1883
    const isElement$6 = isNodeType(1);
1884
    const isHTMLElement = node => isElement$6(node) && isHTMLElement$1(SugarElement.fromDom(node));
1885
    const isSVGElement = node => isElement$6(node) && node.namespaceURI === 'http://www.w3.org/2000/svg';
1886
    const matchNodeName = name => {
1887
      const lowerCasedName = name.toLowerCase();
1888
      return node => isNonNullable(node) && node.nodeName.toLowerCase() === lowerCasedName;
1889
    };
1890
    const matchNodeNames = names => {
1891
      const lowerCasedNames = names.map(s => s.toLowerCase());
1892
      return node => {
1893
        if (node && node.nodeName) {
1894
          const nodeName = node.nodeName.toLowerCase();
1895
          return contains$2(lowerCasedNames, nodeName);
1896
        }
1897
        return false;
1898
      };
1899
    };
1900
    const matchStyleValues = (name, values) => {
1901
      const items = values.toLowerCase().split(' ');
1902
      return node => {
1903
        if (isElement$6(node)) {
1904
          const win = node.ownerDocument.defaultView;
1905
          if (win) {
1906
            for (let i = 0; i < items.length; i++) {
1907
              const computed = win.getComputedStyle(node, null);
1908
              const cssValue = computed ? computed.getPropertyValue(name) : null;
1909
              if (cssValue === items[i]) {
1910
                return true;
1911
              }
1912
            }
1913
          }
1914
        }
1915
        return false;
1916
      };
1917
    };
1918
    const hasAttribute = attrName => {
1919
      return node => {
1920
        return isElement$6(node) && node.hasAttribute(attrName);
1921
      };
1922
    };
1923
    const hasAttributeValue = (attrName, attrValue) => {
1924
      return node => {
1925
        return isElement$6(node) && node.getAttribute(attrName) === attrValue;
1926
      };
1927
    };
1928
    const isBogus$2 = node => isElement$6(node) && node.hasAttribute('data-mce-bogus');
1929
    const isBogusAll$1 = node => isElement$6(node) && node.getAttribute('data-mce-bogus') === 'all';
1930
    const isTable$2 = node => isElement$6(node) && node.tagName === 'TABLE';
1931
    const hasContentEditableState = value => {
1932
      return node => {
1933
        if (isHTMLElement(node)) {
1934
          if (node.contentEditable === value) {
1935
            return true;
1936
          }
1937
          if (node.getAttribute('data-mce-contenteditable') === value) {
1938
            return true;
1939
          }
1940
        }
1941
        return false;
1942
      };
1943
    };
1944
    const isTextareaOrInput = matchNodeNames([
1945
      'textarea',
1946
      'input'
1947
    ]);
1948
    const isText$a = isNodeType(3);
1949
    const isCData = isNodeType(4);
1950
    const isPi = isNodeType(7);
1951
    const isComment = isNodeType(8);
1952
    const isDocument$1 = isNodeType(9);
1953
    const isDocumentFragment = isNodeType(11);
1954
    const isBr$6 = matchNodeName('br');
1955
    const isImg = matchNodeName('img');
1956
    const isContentEditableTrue$3 = hasContentEditableState('true');
1957
    const isContentEditableFalse$b = hasContentEditableState('false');
1958
    const isTableCell$3 = matchNodeNames([
1959
      'td',
1960
      'th'
1961
    ]);
1962
    const isTableCellOrCaption = matchNodeNames([
1963
      'td',
1964
      'th',
1965
      'caption'
1966
    ]);
1967
    const isMedia$2 = matchNodeNames([
1968
      'video',
1969
      'audio',
1970
      'object',
1971
      'embed'
1972
    ]);
1973
    const isListItem$2 = matchNodeName('li');
1974
    const isDetails = matchNodeName('details');
1975
    const isSummary$1 = matchNodeName('summary');
1976
 
1977
    const zeroWidth = '\uFEFF';
1978
    const nbsp = '\xA0';
1979
    const isZwsp$2 = char => char === zeroWidth;
1980
    const removeZwsp = s => s.replace(/\uFEFF/g, '');
1981
 
1982
    const NodeValue = (is, name) => {
1983
      const get = element => {
1984
        if (!is(element)) {
1985
          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
1986
        }
1987
        return getOption(element).getOr('');
1988
      };
1989
      const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
1990
      const set = (element, value) => {
1991
        if (!is(element)) {
1992
          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
1993
        }
1994
        element.dom.nodeValue = value;
1995
      };
1996
      return {
1997
        get,
1998
        getOption,
1999
        set
2000
      };
2001
    };
2002
 
2003
    const api$1 = NodeValue(isText$b, 'text');
2004
    const get$3 = element => api$1.get(element);
2005
    const getOption = element => api$1.getOption(element);
2006
    const set = (element, value) => api$1.set(element, value);
2007
 
2008
    const tableCells = [
2009
      'td',
2010
      'th'
2011
    ];
2012
    const tableSections = [
2013
      'thead',
2014
      'tbody',
2015
      'tfoot'
2016
    ];
2017
    const textBlocks = [
2018
      'h1',
2019
      'h2',
2020
      'h3',
2021
      'h4',
2022
      'h5',
2023
      'h6',
2024
      'p',
2025
      'div',
2026
      'address',
2027
      'pre',
2028
      'form',
2029
      'blockquote',
2030
      'center',
2031
      'dir',
2032
      'fieldset',
2033
      'header',
2034
      'footer',
2035
      'article',
2036
      'section',
2037
      'hgroup',
2038
      'aside',
2039
      'nav',
2040
      'figure'
2041
    ];
2042
    const listItems$1 = [
2043
      'li',
2044
      'dd',
2045
      'dt'
2046
    ];
2047
    const lists = [
2048
      'ul',
2049
      'ol',
2050
      'dl'
2051
    ];
2052
    const wsElements = [
2053
      'pre',
2054
      'script',
2055
      'textarea',
2056
      'style'
2057
    ];
2058
    const lazyLookup = items => {
2059
      let lookup;
2060
      return node => {
2061
        lookup = lookup ? lookup : mapToObject(items, always);
2062
        return has$2(lookup, name(node));
2063
      };
2064
    };
2065
    const isTable$1 = node => name(node) === 'table';
2066
    const isBr$5 = node => isElement$7(node) && name(node) === 'br';
2067
    const isTextBlock$2 = lazyLookup(textBlocks);
2068
    const isList = lazyLookup(lists);
2069
    const isListItem$1 = lazyLookup(listItems$1);
2070
    const isTableSection = lazyLookup(tableSections);
2071
    const isTableCell$2 = lazyLookup(tableCells);
2072
    const isWsPreserveElement = lazyLookup(wsElements);
2073
 
2074
    const getLastChildren$1 = elm => {
2075
      const children = [];
2076
      let rawNode = elm.dom;
2077
      while (rawNode) {
2078
        children.push(SugarElement.fromDom(rawNode));
2079
        rawNode = rawNode.lastChild;
2080
      }
2081
      return children;
2082
    };
2083
    const removeTrailingBr = elm => {
2084
      const allBrs = descendants(elm, 'br');
2085
      const brs = filter$5(getLastChildren$1(elm).slice(-1), isBr$5);
2086
      if (allBrs.length === brs.length) {
2087
        each$e(brs, remove$5);
2088
      }
2089
    };
2090
    const createPaddingBr = () => {
2091
      const br = SugarElement.fromTag('br');
2092
      set$3(br, 'data-mce-bogus', '1');
2093
      return br;
2094
    };
2095
    const fillWithPaddingBr = elm => {
2096
      empty(elm);
2097
      append$1(elm, createPaddingBr());
2098
    };
2099
    const trimBlockTrailingBr = (elm, schema) => {
2100
      lastChild(elm).each(lastChild => {
2101
        prevSibling(lastChild).each(lastChildPrevSibling => {
2102
          if (schema.isBlock(name(elm)) && isBr$5(lastChild) && schema.isBlock(name(lastChildPrevSibling))) {
2103
            remove$5(lastChild);
2104
          }
2105
        });
2106
      });
2107
    };
2108
 
2109
    const ZWSP$1 = zeroWidth;
2110
    const isZwsp$1 = isZwsp$2;
2111
    const trim$2 = removeZwsp;
2112
    const insert$5 = editor => editor.insertContent(ZWSP$1, { preserve_zwsp: true });
2113
 
2114
    const isElement$5 = isElement$6;
2115
    const isText$9 = isText$a;
2116
    const isCaretContainerBlock$1 = node => {
2117
      if (isText$9(node)) {
2118
        node = node.parentNode;
2119
      }
2120
      return isElement$5(node) && node.hasAttribute('data-mce-caret');
2121
    };
2122
    const isCaretContainerInline = node => isText$9(node) && isZwsp$1(node.data);
2123
    const isCaretContainer$2 = node => isCaretContainerBlock$1(node) || isCaretContainerInline(node);
2124
    const hasContent = node => node.firstChild !== node.lastChild || !isBr$6(node.firstChild);
2125
    const insertInline$1 = (node, before) => {
2126
      var _a;
2127
      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
2128
      const textNode = doc.createTextNode(ZWSP$1);
2129
      const parentNode = node.parentNode;
2130
      if (!before) {
2131
        const sibling = node.nextSibling;
2132
        if (isText$9(sibling)) {
2133
          if (isCaretContainer$2(sibling)) {
2134
            return sibling;
2135
          }
2136
          if (startsWithCaretContainer$1(sibling)) {
2137
            sibling.splitText(1);
2138
            return sibling;
2139
          }
2140
        }
2141
        if (node.nextSibling) {
2142
          parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(textNode, node.nextSibling);
2143
        } else {
2144
          parentNode === null || parentNode === void 0 ? void 0 : parentNode.appendChild(textNode);
2145
        }
2146
      } else {
2147
        const sibling = node.previousSibling;
2148
        if (isText$9(sibling)) {
2149
          if (isCaretContainer$2(sibling)) {
2150
            return sibling;
2151
          }
2152
          if (endsWithCaretContainer$1(sibling)) {
2153
            return sibling.splitText(sibling.data.length - 1);
2154
          }
2155
        }
2156
        parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(textNode, node);
2157
      }
2158
      return textNode;
2159
    };
2160
    const isBeforeInline = pos => {
2161
      const container = pos.container();
2162
      if (!isText$a(container)) {
2163
        return false;
2164
      }
2165
      return container.data.charAt(pos.offset()) === ZWSP$1 || pos.isAtStart() && isCaretContainerInline(container.previousSibling);
2166
    };
2167
    const isAfterInline = pos => {
2168
      const container = pos.container();
2169
      if (!isText$a(container)) {
2170
        return false;
2171
      }
2172
      return container.data.charAt(pos.offset() - 1) === ZWSP$1 || pos.isAtEnd() && isCaretContainerInline(container.nextSibling);
2173
    };
2174
    const insertBlock = (blockName, node, before) => {
2175
      var _a;
2176
      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
2177
      const blockNode = doc.createElement(blockName);
2178
      blockNode.setAttribute('data-mce-caret', before ? 'before' : 'after');
2179
      blockNode.setAttribute('data-mce-bogus', 'all');
2180
      blockNode.appendChild(createPaddingBr().dom);
2181
      const parentNode = node.parentNode;
2182
      if (!before) {
2183
        if (node.nextSibling) {
2184
          parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(blockNode, node.nextSibling);
2185
        } else {
2186
          parentNode === null || parentNode === void 0 ? void 0 : parentNode.appendChild(blockNode);
2187
        }
2188
      } else {
2189
        parentNode === null || parentNode === void 0 ? void 0 : parentNode.insertBefore(blockNode, node);
2190
      }
2191
      return blockNode;
2192
    };
2193
    const startsWithCaretContainer$1 = node => isText$9(node) && node.data[0] === ZWSP$1;
2194
    const endsWithCaretContainer$1 = node => isText$9(node) && node.data[node.data.length - 1] === ZWSP$1;
2195
    const trimBogusBr = elm => {
2196
      var _a;
2197
      const brs = elm.getElementsByTagName('br');
2198
      const lastBr = brs[brs.length - 1];
2199
      if (isBogus$2(lastBr)) {
2200
        (_a = lastBr.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(lastBr);
2201
      }
2202
    };
2203
    const showCaretContainerBlock = caretContainer => {
2204
      if (caretContainer && caretContainer.hasAttribute('data-mce-caret')) {
2205
        trimBogusBr(caretContainer);
2206
        caretContainer.removeAttribute('data-mce-caret');
2207
        caretContainer.removeAttribute('data-mce-bogus');
2208
        caretContainer.removeAttribute('style');
2209
        caretContainer.removeAttribute('data-mce-style');
2210
        caretContainer.removeAttribute('_moz_abspos');
2211
        return caretContainer;
2212
      }
2213
      return null;
2214
    };
2215
    const isRangeInCaretContainerBlock = range => isCaretContainerBlock$1(range.startContainer);
2216
 
2217
    const isContentEditableTrue$2 = isContentEditableTrue$3;
2218
    const isContentEditableFalse$a = isContentEditableFalse$b;
2219
    const isBr$4 = isBr$6;
2220
    const isText$8 = isText$a;
2221
    const isInvalidTextElement = matchNodeNames([
2222
      'script',
2223
      'style',
2224
      'textarea'
2225
    ]);
2226
    const isAtomicInline = matchNodeNames([
2227
      'img',
2228
      'input',
2229
      'textarea',
2230
      'hr',
2231
      'iframe',
2232
      'video',
2233
      'audio',
2234
      'object',
2235
      'embed'
2236
    ]);
2237
    const isTable = matchNodeNames(['table']);
2238
    const isCaretContainer$1 = isCaretContainer$2;
2239
    const isCaretCandidate$3 = node => {
2240
      if (isCaretContainer$1(node)) {
2241
        return false;
2242
      }
2243
      if (isText$8(node)) {
2244
        return !isInvalidTextElement(node.parentNode);
2245
      }
2246
      return isAtomicInline(node) || isBr$4(node) || isTable(node) || isNonUiContentEditableFalse(node);
2247
    };
2248
    const isUnselectable = node => isElement$6(node) && node.getAttribute('unselectable') === 'true';
2249
    const isNonUiContentEditableFalse = node => !isUnselectable(node) && isContentEditableFalse$a(node);
2250
    const isInEditable = (node, root) => {
2251
      for (let tempNode = node.parentNode; tempNode && tempNode !== root; tempNode = tempNode.parentNode) {
2252
        if (isNonUiContentEditableFalse(tempNode)) {
2253
          return false;
2254
        }
2255
        if (isContentEditableTrue$2(tempNode)) {
2256
          return true;
2257
        }
2258
      }
2259
      return true;
2260
    };
2261
    const isAtomicContentEditableFalse = node => {
2262
      if (!isNonUiContentEditableFalse(node)) {
2263
        return false;
2264
      }
2265
      return !foldl(from(node.getElementsByTagName('*')), (result, elm) => {
2266
        return result || isContentEditableTrue$2(elm);
2267
      }, false);
2268
    };
2269
    const isAtomic$1 = node => isAtomicInline(node) || isAtomicContentEditableFalse(node);
2270
    const isEditableCaretCandidate$1 = (node, root) => isCaretCandidate$3(node) && isInEditable(node, root);
2271
 
2272
    const whiteSpaceRegExp = /^[ \t\r\n]*$/;
2273
    const isWhitespaceText = text => whiteSpaceRegExp.test(text);
2274
    const isZwsp = text => {
2275
      for (const c of text) {
2276
        if (!isZwsp$2(c)) {
2277
          return false;
2278
        }
2279
      }
2280
      return true;
2281
    };
2282
    const isCollapsibleWhitespace$1 = c => ' \f\t\x0B'.indexOf(c) !== -1;
2283
    const isNewLineChar = c => c === '\n' || c === '\r';
2284
    const isNewline = (text, idx) => idx < text.length && idx >= 0 ? isNewLineChar(text[idx]) : false;
2285
    const normalize$4 = (text, tabSpaces = 4, isStartOfContent = true, isEndOfContent = true) => {
2286
      const tabSpace = repeat(' ', tabSpaces);
2287
      const normalizedText = text.replace(/\t/g, tabSpace);
2288
      const result = foldl(normalizedText, (acc, c) => {
2289
        if (isCollapsibleWhitespace$1(c) || c === nbsp) {
2290
          if (acc.pcIsSpace || acc.str === '' && isStartOfContent || acc.str.length === normalizedText.length - 1 && isEndOfContent || isNewline(normalizedText, acc.str.length + 1)) {
2291
            return {
2292
              pcIsSpace: false,
2293
              str: acc.str + nbsp
2294
            };
2295
          } else {
2296
            return {
2297
              pcIsSpace: true,
2298
              str: acc.str + ' '
2299
            };
2300
          }
2301
        } else {
2302
          return {
2303
            pcIsSpace: isNewLineChar(c),
2304
            str: acc.str + c
2305
          };
2306
        }
2307
      }, {
2308
        pcIsSpace: false,
2309
        str: ''
2310
      });
2311
      return result.str;
2312
    };
2313
 
2314
    const hasWhitespacePreserveParent = (node, rootNode) => {
2315
      const rootElement = SugarElement.fromDom(rootNode);
2316
      const startNode = SugarElement.fromDom(node);
2317
      return ancestor$2(startNode, 'pre,code', curry(eq, rootElement));
2318
    };
2319
    const isWhitespace$1 = (node, rootNode) => {
2320
      return isText$a(node) && isWhitespaceText(node.data) && !hasWhitespacePreserveParent(node, rootNode);
2321
    };
2322
    const isNamedAnchor = node => {
2323
      return isElement$6(node) && node.nodeName === 'A' && !node.hasAttribute('href') && (node.hasAttribute('name') || node.hasAttribute('id'));
2324
    };
2325
    const isContent$1 = (node, rootNode) => {
2326
      return isCaretCandidate$3(node) && !isWhitespace$1(node, rootNode) || isNamedAnchor(node) || isBookmark(node);
2327
    };
2328
    const isBookmark = hasAttribute('data-mce-bookmark');
2329
    const isBogus$1 = hasAttribute('data-mce-bogus');
2330
    const isBogusAll = hasAttributeValue('data-mce-bogus', 'all');
2331
    const hasNonEditableParent = node => parentElement(SugarElement.fromDom(node)).exists(parent => !isEditable$2(parent));
2332
    const isEmptyNode = (targetNode, skipBogus) => {
2333
      let brCount = 0;
2334
      if (isContent$1(targetNode, targetNode)) {
2335
        return false;
2336
      } else {
2337
        let node = targetNode.firstChild;
2338
        if (!node) {
2339
          return true;
2340
        }
2341
        const walker = new DomTreeWalker(node, targetNode);
2342
        do {
2343
          if (skipBogus) {
2344
            if (isBogusAll(node)) {
2345
              node = walker.next(true);
2346
              continue;
2347
            }
2348
            if (isBogus$1(node)) {
2349
              node = walker.next();
2350
              continue;
2351
            }
2352
          }
2353
          if (isContentEditableTrue$3(node) && hasNonEditableParent(node)) {
2354
            return false;
2355
          }
2356
          if (isBr$6(node)) {
2357
            brCount++;
2358
            node = walker.next();
2359
            continue;
2360
          }
2361
          if (isContent$1(node, targetNode)) {
2362
            return false;
2363
          }
2364
          node = walker.next();
2365
        } while (node);
2366
        return brCount <= 1;
2367
      }
2368
    };
2369
    const isEmpty$2 = (elm, skipBogus = true) => isEmptyNode(elm.dom, skipBogus);
2370
 
2371
    const isNonHtmlElementRootName = name => name.toLowerCase() === 'svg';
2372
    const isNonHtmlElementRoot = node => isNonHtmlElementRootName(node.nodeName);
2373
    const toScopeType = node => (node === null || node === void 0 ? void 0 : node.nodeName) === 'svg' ? 'svg' : 'html';
2374
    const namespaceElements = ['svg'];
2375
    const createNamespaceTracker = () => {
2376
      let scopes = [];
2377
      const peek = () => scopes[scopes.length - 1];
2378
      const track = node => {
2379
        if (isNonHtmlElementRoot(node)) {
2380
          scopes.push(node);
2381
        }
2382
        let currentScope = peek();
2383
        if (currentScope && !currentScope.contains(node)) {
2384
          scopes.pop();
2385
          currentScope = peek();
2386
        }
2387
        return toScopeType(currentScope);
2388
      };
2389
      const current = () => toScopeType(peek());
2390
      const reset = () => {
2391
        scopes = [];
2392
      };
2393
      return {
2394
        track,
2395
        current,
2396
        reset
2397
      };
2398
    };
2399
 
2400
    const transparentBlockAttr = 'data-mce-block';
2401
    const elementNames = map => filter$5(keys(map), key => !/[A-Z]/.test(key));
2402
    const makeSelectorFromSchemaMap = map => map$3(elementNames(map), name => {
2403
      return `${ name }:` + map$3(namespaceElements, ns => `not(${ ns } ${ name })`).join(':');
2404
    }).join(',');
2405
    const updateTransparent = (blocksSelector, transparent) => {
2406
      if (isNonNullable(transparent.querySelector(blocksSelector))) {
2407
        transparent.setAttribute(transparentBlockAttr, 'true');
2408
        if (transparent.getAttribute('data-mce-selected') === 'inline-boundary') {
2409
          transparent.removeAttribute('data-mce-selected');
2410
        }
2411
        return true;
2412
      } else {
2413
        transparent.removeAttribute(transparentBlockAttr);
2414
        return false;
2415
      }
2416
    };
2417
    const updateBlockStateOnChildren = (schema, scope) => {
2418
      const transparentSelector = makeSelectorFromSchemaMap(schema.getTransparentElements());
2419
      const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements());
2420
      return filter$5(scope.querySelectorAll(transparentSelector), transparent => updateTransparent(blocksSelector, transparent));
2421
    };
2422
    const trimEdge = (el, leftSide) => {
2423
      var _a;
2424
      const childPropertyName = leftSide ? 'lastChild' : 'firstChild';
2425
      for (let child = el[childPropertyName]; child; child = child[childPropertyName]) {
2426
        if (isEmpty$2(SugarElement.fromDom(child))) {
2427
          (_a = child.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(child);
2428
          return;
2429
        }
2430
      }
2431
    };
2432
    const split$2 = (parentElm, splitElm) => {
2433
      const range = document.createRange();
2434
      const parentNode = parentElm.parentNode;
2435
      if (parentNode) {
2436
        range.setStartBefore(parentElm);
2437
        range.setEndBefore(splitElm);
2438
        const beforeFragment = range.extractContents();
2439
        trimEdge(beforeFragment, true);
2440
        range.setStartAfter(splitElm);
2441
        range.setEndAfter(parentElm);
2442
        const afterFragment = range.extractContents();
2443
        trimEdge(afterFragment, false);
2444
        if (!isEmpty$2(SugarElement.fromDom(beforeFragment))) {
2445
          parentNode.insertBefore(beforeFragment, parentElm);
2446
        }
2447
        if (!isEmpty$2(SugarElement.fromDom(splitElm))) {
2448
          parentNode.insertBefore(splitElm, parentElm);
2449
        }
2450
        if (!isEmpty$2(SugarElement.fromDom(afterFragment))) {
2451
          parentNode.insertBefore(afterFragment, parentElm);
2452
        }
2453
        parentNode.removeChild(parentElm);
2454
      }
2455
    };
2456
    const splitInvalidChildren = (schema, scope, transparentBlocks) => {
2457
      const blocksElements = schema.getBlockElements();
2458
      const rootNode = SugarElement.fromDom(scope);
2459
      const isBlock = el => name(el) in blocksElements;
2460
      const isRoot = el => eq(el, rootNode);
2461
      each$e(fromDom$1(transparentBlocks), transparentBlock => {
2462
        ancestor$4(transparentBlock, isBlock, isRoot).each(parentBlock => {
2463
          const invalidChildren = children(transparentBlock, el => isBlock(el) && !schema.isValidChild(name(parentBlock), name(el)));
2464
          if (invalidChildren.length > 0) {
2465
            const stateScope = parentElement(parentBlock);
2466
            each$e(invalidChildren, child => {
2467
              ancestor$4(child, isBlock, isRoot).each(parentBlock => {
2468
                split$2(parentBlock.dom, child.dom);
2469
              });
2470
            });
2471
            stateScope.each(scope => updateBlockStateOnChildren(schema, scope.dom));
2472
          }
2473
        });
2474
      });
2475
    };
2476
    const unwrapInvalidChildren = (schema, scope, transparentBlocks) => {
2477
      each$e([
2478
        ...transparentBlocks,
2479
        ...isTransparentBlock(schema, scope) ? [scope] : []
2480
      ], block => each$e(descendants(SugarElement.fromDom(block), block.nodeName.toLowerCase()), elm => {
2481
        if (isTransparentInline(schema, elm.dom)) {
2482
          unwrap(elm);
2483
        }
2484
      }));
2485
    };
2486
    const updateChildren = (schema, scope) => {
2487
      const transparentBlocks = updateBlockStateOnChildren(schema, scope);
2488
      splitInvalidChildren(schema, scope, transparentBlocks);
2489
      unwrapInvalidChildren(schema, scope, transparentBlocks);
2490
    };
2491
    const updateElement = (schema, target) => {
2492
      if (isTransparentElement(schema, target)) {
2493
        const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements());
2494
        updateTransparent(blocksSelector, target);
2495
      }
2496
    };
2497
    const updateCaret = (schema, root, caretParent) => {
2498
      const isRoot = el => eq(el, SugarElement.fromDom(root));
2499
      const parents = parents$1(SugarElement.fromDom(caretParent), isRoot);
2500
      get$b(parents, parents.length - 2).filter(isElement$7).fold(() => updateChildren(schema, root), scope => updateChildren(schema, scope.dom));
2501
    };
2502
    const hasBlockAttr = el => el.hasAttribute(transparentBlockAttr);
2503
    const isTransparentElementName = (schema, name) => has$2(schema.getTransparentElements(), name);
2504
    const isTransparentElement = (schema, node) => isElement$6(node) && isTransparentElementName(schema, node.nodeName);
2505
    const isTransparentBlock = (schema, node) => isTransparentElement(schema, node) && hasBlockAttr(node);
2506
    const isTransparentInline = (schema, node) => isTransparentElement(schema, node) && !hasBlockAttr(node);
2507
    const isTransparentAstBlock = (schema, node) => node.type === 1 && isTransparentElementName(schema, node.name) && isString(node.attr(transparentBlockAttr));
2508
 
2509
    const browser$2 = detect$2().browser;
2510
    const firstElement = nodes => find$2(nodes, isElement$7);
2511
    const getTableCaptionDeltaY = elm => {
2512
      if (browser$2.isFirefox() && name(elm) === 'table') {
2513
        return firstElement(children$1(elm)).filter(elm => {
2514
          return name(elm) === 'caption';
2515
        }).bind(caption => {
2516
          return firstElement(nextSiblings(caption)).map(body => {
2517
            const bodyTop = body.dom.offsetTop;
2518
            const captionTop = caption.dom.offsetTop;
2519
            const captionHeight = caption.dom.offsetHeight;
2520
            return bodyTop <= captionTop ? -captionHeight : 0;
2521
          });
2522
        }).getOr(0);
2523
      } else {
2524
        return 0;
2525
      }
2526
    };
2527
    const hasChild = (elm, child) => elm.children && contains$2(elm.children, child);
2528
    const getPos = (body, elm, rootElm) => {
2529
      let x = 0, y = 0;
2530
      const doc = body.ownerDocument;
2531
      rootElm = rootElm ? rootElm : body;
2532
      if (elm) {
2533
        if (rootElm === body && elm.getBoundingClientRect && get$7(SugarElement.fromDom(body), 'position') === 'static') {
2534
          const pos = elm.getBoundingClientRect();
2535
          x = pos.left + (doc.documentElement.scrollLeft || body.scrollLeft) - doc.documentElement.clientLeft;
2536
          y = pos.top + (doc.documentElement.scrollTop || body.scrollTop) - doc.documentElement.clientTop;
2537
          return {
2538
            x,
2539
            y
2540
          };
2541
        }
2542
        let offsetParent = elm;
2543
        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType && !hasChild(offsetParent, rootElm)) {
2544
          const castOffsetParent = offsetParent;
2545
          x += castOffsetParent.offsetLeft || 0;
2546
          y += castOffsetParent.offsetTop || 0;
2547
          offsetParent = castOffsetParent.offsetParent;
2548
        }
2549
        offsetParent = elm.parentNode;
2550
        while (offsetParent && offsetParent !== rootElm && offsetParent.nodeType && !hasChild(offsetParent, rootElm)) {
2551
          x -= offsetParent.scrollLeft || 0;
2552
          y -= offsetParent.scrollTop || 0;
2553
          offsetParent = offsetParent.parentNode;
2554
        }
2555
        y += getTableCaptionDeltaY(SugarElement.fromDom(elm));
2556
      }
2557
      return {
2558
        x,
2559
        y
2560
      };
2561
    };
2562
 
2563
    const StyleSheetLoader = (documentOrShadowRoot, settings = {}) => {
2564
      let idCount = 0;
2565
      const loadedStates = {};
2566
      const edos = SugarElement.fromDom(documentOrShadowRoot);
2567
      const doc = documentOrOwner(edos);
2568
      const _setReferrerPolicy = referrerPolicy => {
2569
        settings.referrerPolicy = referrerPolicy;
2570
      };
2571
      const _setContentCssCors = contentCssCors => {
2572
        settings.contentCssCors = contentCssCors;
2573
      };
2574
      const addStyle = element => {
2575
        append$1(getStyleContainer(edos), element);
2576
      };
2577
      const removeStyle = id => {
2578
        const styleContainer = getStyleContainer(edos);
2579
        descendant$1(styleContainer, '#' + id).each(remove$5);
2580
      };
2581
      const getOrCreateState = url => get$a(loadedStates, url).getOrThunk(() => ({
2582
        id: 'mce-u' + idCount++,
2583
        passed: [],
2584
        failed: [],
2585
        count: 0
2586
      }));
2587
      const load = url => new Promise((success, failure) => {
2588
        let link;
2589
        const urlWithSuffix = Tools._addCacheSuffix(url);
2590
        const state = getOrCreateState(urlWithSuffix);
2591
        loadedStates[urlWithSuffix] = state;
2592
        state.count++;
2593
        const resolve = (callbacks, status) => {
2594
          each$e(callbacks, call);
2595
          state.status = status;
2596
          state.passed = [];
2597
          state.failed = [];
2598
          if (link) {
2599
            link.onload = null;
2600
            link.onerror = null;
2601
            link = null;
2602
          }
2603
        };
2604
        const passed = () => resolve(state.passed, 2);
2605
        const failed = () => resolve(state.failed, 3);
2606
        if (success) {
2607
          state.passed.push(success);
2608
        }
2609
        if (failure) {
2610
          state.failed.push(failure);
2611
        }
2612
        if (state.status === 1) {
2613
          return;
2614
        }
2615
        if (state.status === 2) {
2616
          passed();
2617
          return;
2618
        }
2619
        if (state.status === 3) {
2620
          failed();
2621
          return;
2622
        }
2623
        state.status = 1;
2624
        const linkElem = SugarElement.fromTag('link', doc.dom);
2625
        setAll$1(linkElem, {
2626
          rel: 'stylesheet',
2627
          type: 'text/css',
2628
          id: state.id
2629
        });
2630
        if (settings.contentCssCors) {
2631
          set$3(linkElem, 'crossOrigin', 'anonymous');
2632
        }
2633
        if (settings.referrerPolicy) {
2634
          set$3(linkElem, 'referrerpolicy', settings.referrerPolicy);
2635
        }
2636
        link = linkElem.dom;
2637
        link.onload = passed;
2638
        link.onerror = failed;
2639
        addStyle(linkElem);
2640
        set$3(linkElem, 'href', urlWithSuffix);
2641
      });
2642
      const loadRawCss = (key, css) => {
2643
        const state = getOrCreateState(key);
2644
        loadedStates[key] = state;
2645
        state.count++;
2646
        const styleElem = SugarElement.fromTag('style', doc.dom);
2647
        setAll$1(styleElem, {
2648
          rel: 'stylesheet',
2649
          type: 'text/css',
2650
          id: state.id
2651
        });
2652
        styleElem.dom.innerHTML = css;
2653
        addStyle(styleElem);
2654
      };
2655
      const loadAll = urls => {
2656
        const loadedUrls = Promise.allSettled(map$3(urls, url => load(url).then(constant(url))));
2657
        return loadedUrls.then(results => {
2658
          const parts = partition$2(results, r => r.status === 'fulfilled');
2659
          if (parts.fail.length > 0) {
2660
            return Promise.reject(map$3(parts.fail, result => result.reason));
2661
          } else {
2662
            return map$3(parts.pass, result => result.value);
2663
          }
2664
        });
2665
      };
2666
      const unload = url => {
2667
        const urlWithSuffix = Tools._addCacheSuffix(url);
2668
        get$a(loadedStates, urlWithSuffix).each(state => {
2669
          const count = --state.count;
2670
          if (count === 0) {
2671
            delete loadedStates[urlWithSuffix];
2672
            removeStyle(state.id);
2673
          }
2674
        });
2675
      };
2676
      const unloadRawCss = key => {
2677
        get$a(loadedStates, key).each(state => {
2678
          const count = --state.count;
2679
          if (count === 0) {
2680
            delete loadedStates[key];
2681
            removeStyle(state.id);
2682
          }
2683
        });
2684
      };
2685
      const unloadAll = urls => {
2686
        each$e(urls, url => {
2687
          unload(url);
2688
        });
2689
      };
2690
      return {
2691
        load,
2692
        loadRawCss,
2693
        loadAll,
2694
        unload,
2695
        unloadRawCss,
2696
        unloadAll,
2697
        _setReferrerPolicy,
2698
        _setContentCssCors
2699
      };
2700
    };
2701
 
2702
    const create$d = () => {
2703
      const map = new WeakMap();
2704
      const forElement = (referenceElement, settings) => {
2705
        const root = getRootNode(referenceElement);
2706
        const rootDom = root.dom;
2707
        return Optional.from(map.get(rootDom)).getOrThunk(() => {
2708
          const sl = StyleSheetLoader(rootDom, settings);
2709
          map.set(rootDom, sl);
2710
          return sl;
2711
        });
2712
      };
2713
      return { forElement };
2714
    };
2715
    const instance = create$d();
2716
 
2717
    const isSpan = node => node.nodeName.toLowerCase() === 'span';
2718
    const isInlineContent = (node, root, schema) => isNonNullable(node) && (isContent$1(node, root) || schema.isInline(node.nodeName.toLowerCase()));
2719
    const surroundedByInlineContent = (node, root, schema) => {
2720
      const prev = new DomTreeWalker(node, root).prev(false);
2721
      const next = new DomTreeWalker(node, root).next(false);
2722
      const prevIsInline = isUndefined(prev) || isInlineContent(prev, root, schema);
2723
      const nextIsInline = isUndefined(next) || isInlineContent(next, root, schema);
2724
      return prevIsInline && nextIsInline;
2725
    };
2726
    const isBookmarkNode$2 = node => isSpan(node) && node.getAttribute('data-mce-type') === 'bookmark';
2727
    const isKeepTextNode = (node, root, schema) => isText$a(node) && node.data.length > 0 && surroundedByInlineContent(node, root, schema);
2728
    const isKeepElement = node => isElement$6(node) ? node.childNodes.length > 0 : false;
2729
    const isDocument = node => isDocumentFragment(node) || isDocument$1(node);
2730
    const trimNode = (dom, node, schema, root) => {
2731
      var _a;
2732
      const rootNode = root || node;
2733
      if (isElement$6(node) && isBookmarkNode$2(node)) {
2734
        return node;
2735
      }
2736
      const children = node.childNodes;
2737
      for (let i = children.length - 1; i >= 0; i--) {
2738
        trimNode(dom, children[i], schema, rootNode);
2739
      }
2740
      if (isElement$6(node)) {
2741
        const currentChildren = node.childNodes;
2742
        if (currentChildren.length === 1 && isBookmarkNode$2(currentChildren[0])) {
2743
          (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(currentChildren[0], node);
2744
        }
2745
      }
2746
      if (!isDocument(node) && !isContent$1(node, rootNode) && !isKeepElement(node) && !isKeepTextNode(node, rootNode, schema)) {
2747
        dom.remove(node);
2748
      }
2749
      return node;
2750
    };
2751
 
2752
    const makeMap$3 = Tools.makeMap;
2753
    const attrsCharsRegExp = /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
2754
    const textCharsRegExp = /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
2755
    const rawCharsRegExp = /[<>&\"\']/g;
2756
    const entityRegExp = /&#([a-z0-9]+);?|&([a-z0-9]+);/gi;
2757
    const asciiMap = {
2758
      128: '\u20AC',
2759
      130: '\u201A',
2760
      131: '\u0192',
2761
      132: '\u201E',
2762
      133: '\u2026',
2763
      134: '\u2020',
2764
      135: '\u2021',
2765
      136: '\u02c6',
2766
      137: '\u2030',
2767
      138: '\u0160',
2768
      139: '\u2039',
2769
      140: '\u0152',
2770
      142: '\u017d',
2771
      145: '\u2018',
2772
      146: '\u2019',
2773
      147: '\u201C',
2774
      148: '\u201D',
2775
      149: '\u2022',
2776
      150: '\u2013',
2777
      151: '\u2014',
2778
      152: '\u02DC',
2779
      153: '\u2122',
2780
      154: '\u0161',
2781
      155: '\u203A',
2782
      156: '\u0153',
2783
      158: '\u017e',
2784
      159: '\u0178'
2785
    };
2786
    const baseEntities = {
2787
      '"': '&quot;',
2788
      '\'': '&#39;',
2789
      '<': '&lt;',
2790
      '>': '&gt;',
2791
      '&': '&amp;',
2792
      '`': '&#96;'
2793
    };
2794
    const reverseEntities = {
2795
      '&lt;': '<',
2796
      '&gt;': '>',
2797
      '&amp;': '&',
2798
      '&quot;': '"',
2799
      '&apos;': `'`
2800
    };
2801
    const nativeDecode = text => {
2802
      const elm = SugarElement.fromTag('div').dom;
2803
      elm.innerHTML = text;
2804
      return elm.textContent || elm.innerText || text;
2805
    };
2806
    const buildEntitiesLookup = (items, radix) => {
2807
      const lookup = {};
2808
      if (items) {
2809
        const itemList = items.split(',');
2810
        radix = radix || 10;
2811
        for (let i = 0; i < itemList.length; i += 2) {
2812
          const chr = String.fromCharCode(parseInt(itemList[i], radix));
2813
          if (!baseEntities[chr]) {
2814
            const entity = '&' + itemList[i + 1] + ';';
2815
            lookup[chr] = entity;
2816
            lookup[entity] = chr;
2817
          }
2818
        }
2819
        return lookup;
2820
      } else {
2821
        return undefined;
2822
      }
2823
    };
2824
    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);
2825
    const encodeRaw = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2826
      return baseEntities[chr] || chr;
2827
    });
2828
    const encodeAllRaw = text => ('' + text).replace(rawCharsRegExp, chr => {
2829
      return baseEntities[chr] || chr;
2830
    });
2831
    const encodeNumeric = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2832
      if (chr.length > 1) {
2833
        return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
2834
      }
2835
      return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
2836
    });
2837
    const encodeNamed = (text, attr, entities) => {
2838
      const resolveEntities = entities || namedEntities;
2839
      return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2840
        return baseEntities[chr] || resolveEntities[chr] || chr;
2841
      });
2842
    };
2843
    const getEncodeFunc = (name, entities) => {
2844
      const entitiesMap = buildEntitiesLookup(entities) || namedEntities;
2845
      const encodeNamedAndNumeric = (text, attr) => text.replace(attr ? attrsCharsRegExp : textCharsRegExp, chr => {
2846
        if (baseEntities[chr] !== undefined) {
2847
          return baseEntities[chr];
2848
        }
2849
        if (entitiesMap[chr] !== undefined) {
2850
          return entitiesMap[chr];
2851
        }
2852
        if (chr.length > 1) {
2853
          return '&#' + ((chr.charCodeAt(0) - 55296) * 1024 + (chr.charCodeAt(1) - 56320) + 65536) + ';';
2854
        }
2855
        return '&#' + chr.charCodeAt(0) + ';';
2856
      });
2857
      const encodeCustomNamed = (text, attr) => {
2858
        return encodeNamed(text, attr, entitiesMap);
2859
      };
2860
      const nameMap = makeMap$3(name.replace(/\+/g, ','));
2861
      if (nameMap.named && nameMap.numeric) {
2862
        return encodeNamedAndNumeric;
2863
      }
2864
      if (nameMap.named) {
2865
        if (entities) {
2866
          return encodeCustomNamed;
2867
        }
2868
        return encodeNamed;
2869
      }
2870
      if (nameMap.numeric) {
2871
        return encodeNumeric;
2872
      }
2873
      return encodeRaw;
2874
    };
2875
    const decode = text => text.replace(entityRegExp, (all, numeric) => {
2876
      if (numeric) {
2877
        if (numeric.charAt(0).toLowerCase() === 'x') {
2878
          numeric = parseInt(numeric.substr(1), 16);
2879
        } else {
2880
          numeric = parseInt(numeric, 10);
2881
        }
2882
        if (numeric > 65535) {
2883
          numeric -= 65536;
2884
          return String.fromCharCode(55296 + (numeric >> 10), 56320 + (numeric & 1023));
2885
        }
2886
        return asciiMap[numeric] || String.fromCharCode(numeric);
2887
      }
2888
      return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
2889
    });
2890
    const Entities = {
2891
      encodeRaw,
2892
      encodeAllRaw,
2893
      encodeNumeric,
2894
      encodeNamed,
2895
      getEncodeFunc,
2896
      decode
2897
    };
2898
 
2899
    const split$1 = (items, delim) => {
2900
      items = Tools.trim(items);
2901
      return items ? items.split(delim || ' ') : [];
2902
    };
2903
    const patternToRegExp = str => new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$');
2904
 
2905
    const parseCustomElementsRules = value => {
2906
      const customElementRegExp = /^(~)?(.+)$/;
2907
      return bind$3(split$1(value, ','), rule => {
2908
        const matches = customElementRegExp.exec(rule);
2909
        if (matches) {
2910
          const inline = matches[1] === '~';
2911
          const cloneName = inline ? 'span' : 'div';
2912
          const name = matches[2];
2913
          return [{
2914
              inline,
2915
              cloneName,
2916
              name
2917
            }];
2918
        } else {
2919
          return [];
2920
        }
2921
      });
2922
    };
2923
 
2924
    const getElementSetsAsStrings = type => {
2925
      let globalAttributes, blockContent;
2926
      let phrasingContent;
2927
      globalAttributes = 'id accesskey class dir lang style tabindex title role';
2928
      blockContent = 'address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul';
2929
      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';
2930
      if (type !== 'html4') {
2931
        const transparentContent = 'a ins del canvas map';
2932
        globalAttributes += ' contenteditable contextmenu draggable dropzone ' + 'hidden spellcheck translate';
2933
        blockContent += ' article aside details dialog figure main header footer hgroup section nav ' + transparentContent;
2934
        phrasingContent += ' audio canvas command datalist mark meter output picture ' + 'progress time wbr video ruby bdi keygen svg';
2935
      }
2936
      if (type !== 'html5-strict') {
2937
        globalAttributes += ' xml:lang';
2938
        const html4PhrasingContent = 'acronym applet basefont big font strike tt';
2939
        phrasingContent = [
2940
          phrasingContent,
2941
          html4PhrasingContent
2942
        ].join(' ');
2943
        const html4BlockContent = 'center dir isindex noframes';
2944
        blockContent = [
2945
          blockContent,
2946
          html4BlockContent
2947
        ].join(' ');
2948
      }
2949
      const flowContent = [
2950
        blockContent,
2951
        phrasingContent
2952
      ].join(' ');
2953
      return {
2954
        globalAttributes,
2955
        blockContent,
2956
        phrasingContent,
2957
        flowContent
2958
      };
2959
    };
2960
 
2961
    const makeSchema = type => {
2962
      const {globalAttributes, phrasingContent, flowContent} = getElementSetsAsStrings(type);
2963
      const schema = {};
2964
      const addElement = (name, attributes, children) => {
2965
        schema[name] = {
2966
          attributes: mapToObject(attributes, constant({})),
2967
          attributesOrder: attributes,
2968
          children: mapToObject(children, constant({}))
2969
        };
2970
      };
2971
      const add = (name, attributes = '', children = '') => {
2972
        const childNames = split$1(children);
2973
        const names = split$1(name);
2974
        let ni = names.length;
2975
        const allAttributes = split$1([
2976
          globalAttributes,
2977
          attributes
2978
        ].join(' '));
2979
        while (ni--) {
2980
          addElement(names[ni], allAttributes.slice(), childNames);
2981
        }
2982
      };
2983
      const addAttrs = (name, attributes) => {
2984
        const names = split$1(name);
2985
        const attrs = split$1(attributes);
2986
        let ni = names.length;
2987
        while (ni--) {
2988
          const schemaItem = schema[names[ni]];
2989
          for (let i = 0, l = attrs.length; i < l; i++) {
2990
            schemaItem.attributes[attrs[i]] = {};
2991
            schemaItem.attributesOrder.push(attrs[i]);
2992
          }
2993
        }
2994
      };
2995
      if (type !== 'html5-strict') {
2996
        const html4PhrasingContent = 'acronym applet basefont big font strike tt';
2997
        each$e(split$1(html4PhrasingContent), name => {
2998
          add(name, '', phrasingContent);
2999
        });
3000
        const html4BlockContent = 'center dir isindex noframes';
3001
        each$e(split$1(html4BlockContent), name => {
3002
          add(name, '', flowContent);
3003
        });
3004
      }
3005
      add('html', 'manifest', 'head body');
3006
      add('head', '', 'base command link meta noscript script style title');
3007
      add('title hr noscript br');
3008
      add('base', 'href target');
3009
      add('link', 'href rel media hreflang type sizes hreflang');
3010
      add('meta', 'name http-equiv content charset');
3011
      add('style', 'media type scoped');
3012
      add('script', 'src async defer type charset');
3013
      add('body', 'onafterprint onbeforeprint onbeforeunload onblur onerror onfocus ' + 'onhashchange onload onmessage onoffline ononline onpagehide onpageshow ' + 'onpopstate onresize onscroll onstorage onunload', flowContent);
3014
      add('dd div', '', flowContent);
3015
      add('address dt caption', '', type === 'html4' ? phrasingContent : flowContent);
3016
      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);
3017
      add('blockquote', 'cite', flowContent);
3018
      add('ol', 'reversed start type', 'li');
3019
      add('ul', '', 'li');
3020
      add('li', 'value', flowContent);
3021
      add('dl', '', 'dt dd');
3022
      add('a', 'href target rel media hreflang type', type === 'html4' ? phrasingContent : flowContent);
3023
      add('q', 'cite', phrasingContent);
3024
      add('ins del', 'cite datetime', flowContent);
3025
      add('img', 'src sizes srcset alt usemap ismap width height');
3026
      add('iframe', 'src name width height', flowContent);
3027
      add('embed', 'src type width height');
3028
      add('object', 'data type typemustmatch name usemap form width height', [
3029
        flowContent,
3030
        'param'
3031
      ].join(' '));
3032
      add('param', 'name value');
3033
      add('map', 'name', [
3034
        flowContent,
3035
        'area'
3036
      ].join(' '));
3037
      add('area', 'alt coords shape href target rel media hreflang type');
3038
      add('table', 'border', 'caption colgroup thead tfoot tbody tr' + (type === 'html4' ? ' col' : ''));
3039
      add('colgroup', 'span', 'col');
3040
      add('col', 'span');
3041
      add('tbody thead tfoot', '', 'tr');
3042
      add('tr', '', 'td th');
3043
      add('td', 'colspan rowspan headers', flowContent);
3044
      add('th', 'colspan rowspan headers scope abbr', flowContent);
3045
      add('form', 'accept-charset action autocomplete enctype method name novalidate target', flowContent);
3046
      add('fieldset', 'disabled form name', [
3047
        flowContent,
3048
        'legend'
3049
      ].join(' '));
3050
      add('label', 'form for', phrasingContent);
3051
      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');
3052
      add('button', 'disabled form formaction formenctype formmethod formnovalidate formtarget name type value', type === 'html4' ? flowContent : phrasingContent);
3053
      add('select', 'disabled form multiple name required size', 'option optgroup');
3054
      add('optgroup', 'disabled label', 'option');
3055
      add('option', 'disabled label selected value');
3056
      add('textarea', 'cols dirname disabled form maxlength name readonly required rows wrap');
3057
      add('menu', 'type label', [
3058
        flowContent,
3059
        'li'
3060
      ].join(' '));
3061
      add('noscript', '', flowContent);
3062
      if (type !== 'html4') {
3063
        add('wbr');
3064
        add('ruby', '', [
3065
          phrasingContent,
3066
          'rt rp'
3067
        ].join(' '));
3068
        add('figcaption', '', flowContent);
3069
        add('mark rt rp bdi', '', phrasingContent);
3070
        add('summary', '', [
3071
          phrasingContent,
3072
          'h1 h2 h3 h4 h5 h6'
3073
        ].join(' '));
3074
        add('canvas', 'width height', flowContent);
3075
        add('video', 'src crossorigin poster preload autoplay mediagroup loop ' + 'muted controls width height buffered', [
3076
          flowContent,
3077
          'track source'
3078
        ].join(' '));
3079
        add('audio', 'src crossorigin preload autoplay mediagroup loop muted controls ' + 'buffered volume', [
3080
          flowContent,
3081
          'track source'
3082
        ].join(' '));
3083
        add('picture', '', 'img source');
3084
        add('source', 'src srcset type media sizes');
3085
        add('track', 'kind src srclang label default');
3086
        add('datalist', '', [
3087
          phrasingContent,
3088
          'option'
3089
        ].join(' '));
3090
        add('article section nav aside main header footer', '', flowContent);
3091
        add('hgroup', '', 'h1 h2 h3 h4 h5 h6');
3092
        add('figure', '', [
3093
          flowContent,
3094
          'figcaption'
3095
        ].join(' '));
3096
        add('time', 'datetime', phrasingContent);
3097
        add('dialog', 'open', flowContent);
3098
        add('command', 'type label icon disabled checked radiogroup command');
3099
        add('output', 'for form name', phrasingContent);
3100
        add('progress', 'value max', phrasingContent);
3101
        add('meter', 'value min max low high optimum', phrasingContent);
3102
        add('details', 'open', [
3103
          flowContent,
3104
          'summary'
3105
        ].join(' '));
3106
        add('keygen', 'autofocus challenge disabled form keytype name');
3107
        addElement('svg', 'id tabindex lang xml:space class style x y width height viewBox preserveAspectRatio zoomAndPan transform'.split(' '), []);
3108
      }
3109
      if (type !== 'html5-strict') {
3110
        addAttrs('script', 'language xml:space');
3111
        addAttrs('style', 'xml:space');
3112
        addAttrs('object', 'declare classid code codebase codetype archive standby align border hspace vspace');
3113
        addAttrs('embed', 'align name hspace vspace');
3114
        addAttrs('param', 'valuetype type');
3115
        addAttrs('a', 'charset name rev shape coords');
3116
        addAttrs('br', 'clear');
3117
        addAttrs('applet', 'codebase archive code object alt name width height align hspace vspace');
3118
        addAttrs('img', 'name longdesc align border hspace vspace');
3119
        addAttrs('iframe', 'longdesc frameborder marginwidth marginheight scrolling align');
3120
        addAttrs('font basefont', 'size color face');
3121
        addAttrs('input', 'usemap align');
3122
        addAttrs('select');
3123
        addAttrs('textarea');
3124
        addAttrs('h1 h2 h3 h4 h5 h6 div p legend caption', 'align');
3125
        addAttrs('ul', 'type compact');
3126
        addAttrs('li', 'type');
3127
        addAttrs('ol dl menu dir', 'compact');
3128
        addAttrs('pre', 'width xml:space');
3129
        addAttrs('hr', 'align noshade size width');
3130
        addAttrs('isindex', 'prompt');
3131
        addAttrs('table', 'summary width frame rules cellspacing cellpadding align bgcolor');
3132
        addAttrs('col', 'width align char charoff valign');
3133
        addAttrs('colgroup', 'width align char charoff valign');
3134
        addAttrs('thead', 'align char charoff valign');
3135
        addAttrs('tr', 'align char charoff valign bgcolor');
3136
        addAttrs('th', 'axis align char charoff valign nowrap bgcolor width height');
3137
        addAttrs('form', 'accept');
3138
        addAttrs('td', 'abbr axis scope align char charoff valign nowrap bgcolor width height');
3139
        addAttrs('tfoot', 'align char charoff valign');
3140
        addAttrs('tbody', 'align char charoff valign');
3141
        addAttrs('area', 'nohref');
3142
        addAttrs('body', 'background bgcolor text link vlink alink');
3143
      }
3144
      if (type !== 'html4') {
3145
        addAttrs('input button select textarea', 'autofocus');
3146
        addAttrs('input textarea', 'placeholder');
3147
        addAttrs('a', 'download');
3148
        addAttrs('link script img', 'crossorigin');
3149
        addAttrs('img', 'loading');
3150
        addAttrs('iframe', 'sandbox seamless allow allowfullscreen loading');
3151
      }
3152
      if (type !== 'html4') {
3153
        each$e([
3154
          schema.video,
3155
          schema.audio
3156
        ], item => {
3157
          delete item.children.audio;
3158
          delete item.children.video;
3159
        });
3160
      }
3161
      each$e(split$1('a form meter progress dfn'), name => {
3162
        if (schema[name]) {
3163
          delete schema[name].children[name];
3164
        }
3165
      });
3166
      delete schema.caption.children.table;
3167
      delete schema.script;
3168
      return schema;
3169
    };
3170
 
3171
    const prefixToOperation = prefix => prefix === '-' ? 'remove' : 'add';
3172
    const parseValidChildrenRules = value => {
3173
      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]+)\[([^\]]+)]$/;
3174
      return bind$3(split$1(value, ','), rule => {
3175
        const matches = childRuleRegExp.exec(rule);
3176
        if (matches) {
3177
          const prefix = matches[1];
3178
          const operation = prefix ? prefixToOperation(prefix) : 'replace';
3179
          const name = matches[2];
3180
          const validChildren = split$1(matches[3], '|');
3181
          return [{
3182
              operation,
3183
              name,
3184
              validChildren
3185
            }];
3186
        } else {
3187
          return [];
3188
        }
3189
      });
3190
    };
3191
 
3192
    const parseValidElementsAttrDataIntoElement = (attrData, targetElement) => {
3193
      const attrRuleRegExp = /^([!\-])?(\w+[\\:]:\w+|[^=~<]+)?(?:([=~<])(.*))?$/;
3194
      const hasPatternsRegExp = /[*?+]/;
3195
      const {attributes, attributesOrder} = targetElement;
3196
      return each$e(split$1(attrData, '|'), rule => {
3197
        const matches = attrRuleRegExp.exec(rule);
3198
        if (matches) {
3199
          const attr = {};
3200
          const attrType = matches[1];
3201
          const attrName = matches[2].replace(/[\\:]:/g, ':');
3202
          const attrPrefix = matches[3];
3203
          const value = matches[4];
3204
          if (attrType === '!') {
3205
            targetElement.attributesRequired = targetElement.attributesRequired || [];
3206
            targetElement.attributesRequired.push(attrName);
3207
            attr.required = true;
3208
          }
3209
          if (attrType === '-') {
3210
            delete attributes[attrName];
3211
            attributesOrder.splice(Tools.inArray(attributesOrder, attrName), 1);
3212
            return;
3213
          }
3214
          if (attrPrefix) {
3215
            if (attrPrefix === '=') {
3216
              targetElement.attributesDefault = targetElement.attributesDefault || [];
3217
              targetElement.attributesDefault.push({
3218
                name: attrName,
3219
                value
3220
              });
3221
              attr.defaultValue = value;
3222
            } else if (attrPrefix === '~') {
3223
              targetElement.attributesForced = targetElement.attributesForced || [];
3224
              targetElement.attributesForced.push({
3225
                name: attrName,
3226
                value
3227
              });
3228
              attr.forcedValue = value;
3229
            } else if (attrPrefix === '<') {
3230
              attr.validValues = Tools.makeMap(value, '?');
3231
            }
3232
          }
3233
          if (hasPatternsRegExp.test(attrName)) {
3234
            const attrPattern = attr;
3235
            targetElement.attributePatterns = targetElement.attributePatterns || [];
3236
            attrPattern.pattern = patternToRegExp(attrName);
3237
            targetElement.attributePatterns.push(attrPattern);
3238
          } else {
3239
            if (!attributes[attrName]) {
3240
              attributesOrder.push(attrName);
3241
            }
3242
            attributes[attrName] = attr;
3243
          }
3244
        }
3245
      });
3246
    };
3247
    const cloneAttributesInto = (from, to) => {
3248
      each$d(from.attributes, (value, key) => {
3249
        to.attributes[key] = value;
3250
      });
3251
      to.attributesOrder.push(...from.attributesOrder);
3252
    };
3253
    const parseValidElementsRules = (globalElement, validElements) => {
3254
      const elementRuleRegExp = /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)])?$/;
3255
      return bind$3(split$1(validElements, ','), rule => {
3256
        const matches = elementRuleRegExp.exec(rule);
3257
        if (matches) {
3258
          const prefix = matches[1];
3259
          const elementName = matches[2];
3260
          const outputName = matches[3];
3261
          const attrsPrefix = matches[4];
3262
          const attrData = matches[5];
3263
          const element = {
3264
            attributes: {},
3265
            attributesOrder: []
3266
          };
3267
          globalElement.each(el => cloneAttributesInto(el, element));
3268
          if (prefix === '#') {
3269
            element.paddEmpty = true;
3270
          } else if (prefix === '-') {
3271
            element.removeEmpty = true;
3272
          }
3273
          if (attrsPrefix === '!') {
3274
            element.removeEmptyAttrs = true;
3275
          }
3276
          if (attrData) {
3277
            parseValidElementsAttrDataIntoElement(attrData, element);
3278
          }
3279
          if (outputName) {
3280
            element.outputName = elementName;
3281
          }
3282
          if (elementName === '@') {
3283
            if (globalElement.isNone()) {
3284
              globalElement = Optional.some(element);
3285
            } else {
3286
              return [];
3287
            }
3288
          }
3289
          return [outputName ? {
3290
              name: elementName,
3291
              element,
3292
              aliasName: outputName
3293
            } : {
3294
              name: elementName,
3295
              element
3296
            }];
3297
        } else {
3298
          return [];
3299
        }
3300
      });
3301
    };
3302
 
3303
    const mapCache = {};
3304
    const makeMap$2 = Tools.makeMap, each$b = Tools.each, extend$2 = Tools.extend, explode$2 = Tools.explode;
3305
    const createMap = (defaultValue, extendWith = {}) => {
3306
      const value = makeMap$2(defaultValue, ' ', makeMap$2(defaultValue.toUpperCase(), ' '));
3307
      return extend$2(value, extendWith);
3308
    };
3309
    const getTextRootBlockElements = schema => createMap('td th li dt dd figcaption caption details summary', schema.getTextBlockElements());
3310
    const compileElementMap = (value, mode) => {
3311
      if (value) {
3312
        const styles = {};
3313
        if (isString(value)) {
3314
          value = { '*': value };
3315
        }
3316
        each$b(value, (value, key) => {
3317
          styles[key] = styles[key.toUpperCase()] = mode === 'map' ? makeMap$2(value, /[, ]/) : explode$2(value, /[, ]/);
3318
        });
3319
        return styles;
3320
      } else {
3321
        return undefined;
3322
      }
3323
    };
3324
    const Schema = (settings = {}) => {
3325
      var _a;
3326
      const elements = {};
3327
      const children = {};
3328
      let patternElements = [];
3329
      const customElementsMap = {};
3330
      const specialElements = {};
3331
      const createLookupTable = (option, defaultValue, extendWith) => {
3332
        const value = settings[option];
3333
        if (!value) {
3334
          let newValue = mapCache[option];
3335
          if (!newValue) {
3336
            newValue = createMap(defaultValue, extendWith);
3337
            mapCache[option] = newValue;
3338
          }
3339
          return newValue;
3340
        } else {
3341
          return makeMap$2(value, /[, ]/, makeMap$2(value.toUpperCase(), /[, ]/));
3342
        }
3343
      };
3344
      const schemaType = (_a = settings.schema) !== null && _a !== void 0 ? _a : 'html5';
3345
      const schemaItems = makeSchema(schemaType);
3346
      if (settings.verify_html === false) {
3347
        settings.valid_elements = '*[*]';
3348
      }
3349
      const validStyles = compileElementMap(settings.valid_styles);
3350
      const invalidStyles = compileElementMap(settings.invalid_styles, 'map');
3351
      const validClasses = compileElementMap(settings.valid_classes, 'map');
3352
      const whitespaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea video audio iframe object code');
3353
      const selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');
3354
      const voidElementsMap = createLookupTable('void_elements', 'area base basefont br col frame hr img input isindex link ' + 'meta param embed source wbr track');
3355
      const boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize ' + 'noshade nowrap readonly selected autoplay loop controls allowfullscreen');
3356
      const nonEmptyOrMoveCaretBeforeOnEnter = 'td th iframe video audio object script code';
3357
      const nonEmptyElementsMap = createLookupTable('non_empty_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' pre svg', voidElementsMap);
3358
      const moveCaretBeforeOnEnterElementsMap = createLookupTable('move_caret_before_on_enter_elements', nonEmptyOrMoveCaretBeforeOnEnter + ' table', voidElementsMap);
3359
      const headings = 'h1 h2 h3 h4 h5 h6';
3360
      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');
3361
      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);
3362
      const textInlineElementsMap = createLookupTable('text_inline_elements', 'span strong b em i font s strike u var cite ' + 'dfn code mark q sup sub samp');
3363
      const transparentElementsMap = createLookupTable('transparent_elements', 'a ins del canvas map');
3364
      const wrapBlockElementsMap = createLookupTable('wrap_block_elements', 'pre ' + headings);
3365
      each$b('script noscript iframe noframes noembed title style textarea xmp plaintext'.split(' '), name => {
3366
        specialElements[name] = new RegExp('</' + name + '[^>]*>', 'gi');
3367
      });
3368
      const addValidElements = validElements => {
3369
        const globalElement = Optional.from(elements['@']);
3370
        const hasPatternsRegExp = /[*?+]/;
3371
        each$e(parseValidElementsRules(globalElement, validElements !== null && validElements !== void 0 ? validElements : ''), ({name, element, aliasName}) => {
3372
          if (aliasName) {
3373
            elements[aliasName] = element;
3374
          }
3375
          if (hasPatternsRegExp.test(name)) {
3376
            const patternElement = element;
3377
            patternElement.pattern = patternToRegExp(name);
3378
            patternElements.push(patternElement);
3379
          } else {
3380
            elements[name] = element;
3381
          }
3382
        });
3383
      };
3384
      const setValidElements = validElements => {
3385
        patternElements = [];
3386
        each$e(keys(elements), name => {
3387
          delete elements[name];
3388
        });
3389
        addValidElements(validElements);
3390
      };
3391
      const addCustomElements = customElements => {
3392
        delete mapCache.text_block_elements;
3393
        delete mapCache.block_elements;
3394
        each$e(parseCustomElementsRules(customElements !== null && customElements !== void 0 ? customElements : ''), ({inline, name, cloneName}) => {
3395
          children[name] = children[cloneName];
3396
          customElementsMap[name] = cloneName;
3397
          nonEmptyElementsMap[name.toUpperCase()] = {};
3398
          nonEmptyElementsMap[name] = {};
3399
          if (!inline) {
3400
            blockElementsMap[name.toUpperCase()] = {};
3401
            blockElementsMap[name] = {};
3402
          }
3403
          if (!elements[name]) {
3404
            let customRule = elements[cloneName];
3405
            customRule = extend$2({}, customRule);
3406
            delete customRule.removeEmptyAttrs;
3407
            delete customRule.removeEmpty;
3408
            elements[name] = customRule;
3409
          }
3410
          each$d(children, (element, elmName) => {
3411
            if (element[cloneName]) {
3412
              children[elmName] = element = extend$2({}, children[elmName]);
3413
              element[name] = element[cloneName];
3414
            }
3415
          });
3416
        });
3417
      };
3418
      const addValidChildren = validChildren => {
3419
        each$e(parseValidChildrenRules(validChildren !== null && validChildren !== void 0 ? validChildren : ''), ({operation, name, validChildren}) => {
3420
          const parent = operation === 'replace' ? { '#comment': {} } : children[name];
3421
          each$e(validChildren, child => {
3422
            if (operation === 'remove') {
3423
              delete parent[child];
3424
            } else {
3425
              parent[child] = {};
3426
            }
3427
          });
3428
          children[name] = parent;
3429
        });
3430
      };
3431
      const getElementRule = name => {
3432
        const element = elements[name];
3433
        if (element) {
3434
          return element;
3435
        }
3436
        let i = patternElements.length;
3437
        while (i--) {
3438
          const patternElement = patternElements[i];
3439
          if (patternElement.pattern.test(name)) {
3440
            return patternElement;
3441
          }
3442
        }
3443
        return undefined;
3444
      };
3445
      if (!settings.valid_elements) {
3446
        each$b(schemaItems, (element, name) => {
3447
          elements[name] = {
3448
            attributes: element.attributes,
3449
            attributesOrder: element.attributesOrder
3450
          };
3451
          children[name] = element.children;
3452
        });
3453
        each$b(split$1('strong/b em/i'), item => {
3454
          const items = split$1(item, '/');
3455
          elements[items[1]].outputName = items[0];
3456
        });
3457
        each$b(textInlineElementsMap, (_val, name) => {
3458
          if (elements[name]) {
3459
            if (settings.padd_empty_block_inline_children) {
3460
              elements[name].paddInEmptyBlock = true;
3461
            }
3462
            elements[name].removeEmpty = true;
3463
          }
3464
        });
3465
        each$b(split$1('ol ul blockquote a table tbody'), name => {
3466
          if (elements[name]) {
3467
            elements[name].removeEmpty = true;
3468
          }
3469
        });
3470
        each$b(split$1('p h1 h2 h3 h4 h5 h6 th td pre div address caption li summary'), name => {
3471
          if (elements[name]) {
3472
            elements[name].paddEmpty = true;
3473
          }
3474
        });
3475
        each$b(split$1('span'), name => {
3476
          elements[name].removeEmptyAttrs = true;
3477
        });
3478
      } else {
3479
        setValidElements(settings.valid_elements);
3480
        each$b(schemaItems, (element, name) => {
3481
          children[name] = element.children;
3482
        });
3483
      }
3484
      delete elements.svg;
3485
      addCustomElements(settings.custom_elements);
3486
      addValidChildren(settings.valid_children);
3487
      addValidElements(settings.extended_valid_elements);
3488
      addValidChildren('+ol[ul|ol],+ul[ul|ol]');
3489
      each$b({
3490
        dd: 'dl',
3491
        dt: 'dl',
3492
        li: 'ul ol',
3493
        td: 'tr',
3494
        th: 'tr',
3495
        tr: 'tbody thead tfoot',
3496
        tbody: 'table',
3497
        thead: 'table',
3498
        tfoot: 'table',
3499
        legend: 'fieldset',
3500
        area: 'map',
3501
        param: 'video audio object'
3502
      }, (parents, item) => {
3503
        if (elements[item]) {
3504
          elements[item].parentsRequired = split$1(parents);
3505
        }
3506
      });
3507
      if (settings.invalid_elements) {
3508
        each$b(explode$2(settings.invalid_elements), item => {
3509
          if (elements[item]) {
3510
            delete elements[item];
3511
          }
3512
        });
3513
      }
3514
      if (!getElementRule('span')) {
3515
        addValidElements('span[!data-mce-type|*]');
3516
      }
3517
      const getValidStyles = constant(validStyles);
3518
      const getInvalidStyles = constant(invalidStyles);
3519
      const getValidClasses = constant(validClasses);
3520
      const getBoolAttrs = constant(boolAttrMap);
3521
      const getBlockElements = constant(blockElementsMap);
3522
      const getTextBlockElements = constant(textBlockElementsMap);
3523
      const getTextInlineElements = constant(textInlineElementsMap);
3524
      const getVoidElements = constant(Object.seal(voidElementsMap));
3525
      const getSelfClosingElements = constant(selfClosingElementsMap);
3526
      const getNonEmptyElements = constant(nonEmptyElementsMap);
3527
      const getMoveCaretBeforeOnEnterElements = constant(moveCaretBeforeOnEnterElementsMap);
3528
      const getWhitespaceElements = constant(whitespaceElementsMap);
3529
      const getTransparentElements = constant(transparentElementsMap);
3530
      const getWrapBlockElements = constant(wrapBlockElementsMap);
3531
      const getSpecialElements = constant(Object.seal(specialElements));
3532
      const isValidChild = (name, child) => {
3533
        const parent = children[name.toLowerCase()];
3534
        return !!(parent && parent[child.toLowerCase()]);
3535
      };
3536
      const isValid = (name, attr) => {
3537
        const rule = getElementRule(name);
3538
        if (rule) {
3539
          if (attr) {
3540
            if (rule.attributes[attr]) {
3541
              return true;
3542
            }
3543
            const attrPatterns = rule.attributePatterns;
3544
            if (attrPatterns) {
3545
              let i = attrPatterns.length;
3546
              while (i--) {
3547
                if (attrPatterns[i].pattern.test(attr)) {
3548
                  return true;
3549
                }
3550
              }
3551
            }
3552
          } else {
3553
            return true;
3554
          }
3555
        }
3556
        return false;
3557
      };
3558
      const isBlock = name => has$2(getBlockElements(), name);
3559
      const isInline = name => !startsWith(name, '#') && isValid(name) && !isBlock(name);
3560
      const isWrapper = name => has$2(getWrapBlockElements(), name) || isInline(name);
3561
      const getCustomElements = constant(customElementsMap);
3562
      return {
3563
        type: schemaType,
3564
        children,
3565
        elements,
3566
        getValidStyles,
3567
        getValidClasses,
3568
        getBlockElements,
3569
        getInvalidStyles,
3570
        getVoidElements,
3571
        getTextBlockElements,
3572
        getTextInlineElements,
3573
        getBoolAttrs,
3574
        getElementRule,
3575
        getSelfClosingElements,
3576
        getNonEmptyElements,
3577
        getMoveCaretBeforeOnEnterElements,
3578
        getWhitespaceElements,
3579
        getTransparentElements,
3580
        getSpecialElements,
3581
        isValidChild,
3582
        isValid,
3583
        isBlock,
3584
        isInline,
3585
        isWrapper,
3586
        getCustomElements,
3587
        addValidElements,
3588
        setValidElements,
3589
        addCustomElements,
3590
        addValidChildren
3591
      };
3592
    };
3593
 
3594
    const hexColour = value => ({ value: normalizeHex(value) });
3595
    const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
3596
    const toHex = component => {
3597
      const hex = component.toString(16);
3598
      return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
3599
    };
3600
    const fromRgba = rgbaColour => {
3601
      const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
3602
      return hexColour(value);
3603
    };
3604
 
3605
    const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
3606
    const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
3607
    const rgbaColour = (red, green, blue, alpha) => ({
3608
      red,
3609
      green,
3610
      blue,
3611
      alpha
3612
    });
3613
    const fromStringValues = (red, green, blue, alpha) => {
3614
      const r = parseInt(red, 10);
3615
      const g = parseInt(green, 10);
3616
      const b = parseInt(blue, 10);
3617
      const a = parseFloat(alpha);
3618
      return rgbaColour(r, g, b, a);
3619
    };
3620
    const fromString = rgbaString => {
3621
      if (rgbaString === 'transparent') {
3622
        return Optional.some(rgbaColour(0, 0, 0, 0));
3623
      }
3624
      const rgbMatch = rgbRegex.exec(rgbaString);
3625
      if (rgbMatch !== null) {
3626
        return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
3627
      }
3628
      const rgbaMatch = rgbaRegex.exec(rgbaString);
3629
      if (rgbaMatch !== null) {
3630
        return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
3631
      }
3632
      return Optional.none();
3633
    };
3634
    const toString = rgba => `rgba(${ rgba.red },${ rgba.green },${ rgba.blue },${ rgba.alpha })`;
3635
 
3636
    const rgbaToHexString = color => fromString(color).map(fromRgba).map(h => '#' + h.value).getOr(color);
3637
 
3638
    const Styles = (settings = {}, schema) => {
3639
      const urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi;
3640
      const styleRegExp = /\s*([^:]+):\s*([^;]+);?/g;
3641
      const trimRightRegExp = /\s+$/;
3642
      const encodingLookup = {};
3643
      let validStyles;
3644
      let invalidStyles;
3645
      const invisibleChar = zeroWidth;
3646
      if (schema) {
3647
        validStyles = schema.getValidStyles();
3648
        invalidStyles = schema.getInvalidStyles();
3649
      }
3650
      const encodingItems = (`\\" \\' \\; \\: ; : ` + invisibleChar).split(' ');
3651
      for (let i = 0; i < encodingItems.length; i++) {
3652
        encodingLookup[encodingItems[i]] = invisibleChar + i;
3653
        encodingLookup[invisibleChar + i] = encodingItems[i];
3654
      }
3655
      const self = {
3656
        parse: css => {
3657
          const styles = {};
3658
          let isEncoded = false;
3659
          const urlConverter = settings.url_converter;
3660
          const urlConverterScope = settings.url_converter_scope || self;
3661
          const compress = (prefix, suffix, noJoin) => {
3662
            const top = styles[prefix + '-top' + suffix];
3663
            if (!top) {
3664
              return;
3665
            }
3666
            const right = styles[prefix + '-right' + suffix];
3667
            if (!right) {
3668
              return;
3669
            }
3670
            const bottom = styles[prefix + '-bottom' + suffix];
3671
            if (!bottom) {
3672
              return;
3673
            }
3674
            const left = styles[prefix + '-left' + suffix];
3675
            if (!left) {
3676
              return;
3677
            }
3678
            const box = [
3679
              top,
3680
              right,
3681
              bottom,
3682
              left
3683
            ];
3684
            let i = box.length - 1;
3685
            while (i--) {
3686
              if (box[i] !== box[i + 1]) {
3687
                break;
3688
              }
3689
            }
3690
            if (i > -1 && noJoin) {
3691
              return;
3692
            }
3693
            styles[prefix + suffix] = i === -1 ? box[0] : box.join(' ');
3694
            delete styles[prefix + '-top' + suffix];
3695
            delete styles[prefix + '-right' + suffix];
3696
            delete styles[prefix + '-bottom' + suffix];
3697
            delete styles[prefix + '-left' + suffix];
3698
          };
3699
          const canCompress = key => {
3700
            const value = styles[key];
3701
            if (!value) {
3702
              return;
3703
            }
3704
            const values = value.indexOf(',') > -1 ? [value] : value.split(' ');
3705
            let i = values.length;
3706
            while (i--) {
3707
              if (values[i] !== values[0]) {
3708
                return false;
3709
              }
3710
            }
3711
            styles[key] = values[0];
3712
            return true;
3713
          };
3714
          const compress2 = (target, a, b, c) => {
3715
            if (!canCompress(a)) {
3716
              return;
3717
            }
3718
            if (!canCompress(b)) {
3719
              return;
3720
            }
3721
            if (!canCompress(c)) {
3722
              return;
3723
            }
3724
            styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c];
3725
            delete styles[a];
3726
            delete styles[b];
3727
            delete styles[c];
3728
          };
3729
          const encode = str => {
3730
            isEncoded = true;
3731
            return encodingLookup[str];
3732
          };
3733
          const decode = (str, keepSlashes) => {
3734
            if (isEncoded) {
3735
              str = str.replace(/\uFEFF[0-9]/g, str => {
3736
                return encodingLookup[str];
3737
              });
3738
            }
3739
            if (!keepSlashes) {
3740
              str = str.replace(/\\([\'\";:])/g, '$1');
3741
            }
3742
            return str;
3743
          };
3744
          const decodeSingleHexSequence = escSeq => {
3745
            return String.fromCharCode(parseInt(escSeq.slice(1), 16));
3746
          };
3747
          const decodeHexSequences = value => {
3748
            return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence);
3749
          };
3750
          const processUrl = (match, url, url2, url3, str, str2) => {
3751
            str = str || str2;
3752
            if (str) {
3753
              str = decode(str);
3754
              return `'` + str.replace(/\'/g, `\\'`) + `'`;
3755
            }
3756
            url = decode(url || url2 || url3 || '');
3757
            if (!settings.allow_script_urls) {
3758
              const scriptUrl = url.replace(/[\s\r\n]+/g, '');
3759
              if (/(java|vb)script:/i.test(scriptUrl)) {
3760
                return '';
3761
              }
3762
              if (!settings.allow_svg_data_urls && /^data:image\/svg/i.test(scriptUrl)) {
3763
                return '';
3764
              }
3765
            }
3766
            if (urlConverter) {
3767
              url = urlConverter.call(urlConverterScope, url, 'style');
3768
            }
3769
            return `url('` + url.replace(/\'/g, `\\'`) + `')`;
3770
          };
3771
          if (css) {
3772
            css = css.replace(/[\u0000-\u001F]/g, '');
3773
            css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, str => {
3774
              return str.replace(/[;:]/g, encode);
3775
            });
3776
            let matches;
3777
            while (matches = styleRegExp.exec(css)) {
3778
              styleRegExp.lastIndex = matches.index + matches[0].length;
3779
              let name = matches[1].replace(trimRightRegExp, '').toLowerCase();
3780
              let value = matches[2].replace(trimRightRegExp, '');
3781
              if (name && value) {
3782
                name = decodeHexSequences(name);
3783
                value = decodeHexSequences(value);
3784
                if (name.indexOf(invisibleChar) !== -1 || name.indexOf('"') !== -1) {
3785
                  continue;
3786
                }
3787
                if (!settings.allow_script_urls && (name === 'behavior' || /expression\s*\(|\/\*|\*\//.test(value))) {
3788
                  continue;
3789
                }
3790
                if (name === 'font-weight' && value === '700') {
3791
                  value = 'bold';
3792
                } else if (name === 'color' || name === 'background-color') {
3793
                  value = value.toLowerCase();
3794
                }
3795
                if (isString(settings.force_hex_color) && settings.force_hex_color !== 'off') {
3796
                  fromString(value).each(rgba => {
3797
                    if (settings.force_hex_color === 'always' || rgba.alpha === 1) {
3798
                      value = rgbaToHexString(toString(rgba));
3799
                    }
3800
                  });
3801
                }
3802
                value = value.replace(urlOrStrRegExp, processUrl);
3803
                styles[name] = isEncoded ? decode(value, true) : value;
3804
              }
3805
            }
3806
            compress('border', '', true);
3807
            compress('border', '-width');
3808
            compress('border', '-color');
3809
            compress('border', '-style');
3810
            compress('padding', '');
3811
            compress('margin', '');
3812
            compress2('border', 'border-width', 'border-style', 'border-color');
3813
            if (styles.border === 'medium none') {
3814
              delete styles.border;
3815
            }
3816
            if (styles['border-image'] === 'none') {
3817
              delete styles['border-image'];
3818
            }
3819
          }
3820
          return styles;
3821
        },
3822
        serialize: (styles, elementName) => {
3823
          let css = '';
3824
          const serializeStyles = (elemName, validStyleList) => {
3825
            const styleList = validStyleList[elemName];
3826
            if (styleList) {
3827
              for (let i = 0, l = styleList.length; i < l; i++) {
3828
                const name = styleList[i];
3829
                const value = styles[name];
3830
                if (value) {
3831
                  css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
3832
                }
3833
              }
3834
            }
3835
          };
3836
          const isValid = (name, elemName) => {
3837
            if (!invalidStyles || !elemName) {
3838
              return true;
3839
            }
3840
            let styleMap = invalidStyles['*'];
3841
            if (styleMap && styleMap[name]) {
3842
              return false;
3843
            }
3844
            styleMap = invalidStyles[elemName];
3845
            return !(styleMap && styleMap[name]);
3846
          };
3847
          if (elementName && validStyles) {
3848
            serializeStyles('*', validStyles);
3849
            serializeStyles(elementName, validStyles);
3850
          } else {
3851
            each$d(styles, (value, name) => {
3852
              if (value && isValid(name, elementName)) {
3853
                css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
3854
              }
3855
            });
3856
          }
3857
          return css;
3858
        }
3859
      };
3860
      return self;
3861
    };
3862
 
3863
    const deprecated = {
3864
      keyLocation: true,
3865
      layerX: true,
3866
      layerY: true,
3867
      returnValue: true,
3868
      webkitMovementX: true,
3869
      webkitMovementY: true,
3870
      keyIdentifier: true,
3871
      mozPressure: true
3872
    };
3873
    const isNativeEvent = event => event instanceof Event || isFunction(event.initEvent);
3874
    const hasIsDefaultPrevented = event => event.isDefaultPrevented === always || event.isDefaultPrevented === never;
3875
    const needsNormalizing = event => isNullable(event.preventDefault) || isNativeEvent(event);
3876
    const clone$3 = (originalEvent, data) => {
3877
      const event = data !== null && data !== void 0 ? data : {};
3878
      for (const name in originalEvent) {
3879
        if (!has$2(deprecated, name)) {
3880
          event[name] = originalEvent[name];
3881
        }
3882
      }
3883
      if (isNonNullable(originalEvent.composedPath)) {
3884
        event.composedPath = () => originalEvent.composedPath();
3885
      }
3886
      if (isNonNullable(originalEvent.getModifierState)) {
3887
        event.getModifierState = keyArg => originalEvent.getModifierState(keyArg);
3888
      }
3889
      if (isNonNullable(originalEvent.getTargetRanges)) {
3890
        event.getTargetRanges = () => originalEvent.getTargetRanges();
3891
      }
3892
      return event;
3893
    };
3894
    const normalize$3 = (type, originalEvent, fallbackTarget, data) => {
3895
      var _a;
3896
      const event = clone$3(originalEvent, data);
3897
      event.type = type;
3898
      if (isNullable(event.target)) {
3899
        event.target = (_a = event.srcElement) !== null && _a !== void 0 ? _a : fallbackTarget;
3900
      }
3901
      if (needsNormalizing(originalEvent)) {
3902
        event.preventDefault = () => {
3903
          event.defaultPrevented = true;
3904
          event.isDefaultPrevented = always;
3905
          if (isFunction(originalEvent.preventDefault)) {
3906
            originalEvent.preventDefault();
3907
          }
3908
        };
3909
        event.stopPropagation = () => {
3910
          event.cancelBubble = true;
3911
          event.isPropagationStopped = always;
3912
          if (isFunction(originalEvent.stopPropagation)) {
3913
            originalEvent.stopPropagation();
3914
          }
3915
        };
3916
        event.stopImmediatePropagation = () => {
3917
          event.isImmediatePropagationStopped = always;
3918
          event.stopPropagation();
3919
        };
3920
        if (!hasIsDefaultPrevented(event)) {
3921
          event.isDefaultPrevented = event.defaultPrevented === true ? always : never;
3922
          event.isPropagationStopped = event.cancelBubble === true ? always : never;
3923
          event.isImmediatePropagationStopped = never;
3924
        }
3925
      }
3926
      return event;
3927
    };
3928
 
3929
    const eventExpandoPrefix = 'mce-data-';
3930
    const mouseEventRe = /^(?:mouse|contextmenu)|click/;
3931
    const addEvent = (target, name, callback, capture) => {
3932
      target.addEventListener(name, callback, capture || false);
3933
    };
3934
    const removeEvent = (target, name, callback, capture) => {
3935
      target.removeEventListener(name, callback, capture || false);
3936
    };
3937
    const isMouseEvent = event => isNonNullable(event) && mouseEventRe.test(event.type);
3938
    const fix = (originalEvent, data) => {
3939
      const event = normalize$3(originalEvent.type, originalEvent, document, data);
3940
      if (isMouseEvent(originalEvent) && isUndefined(originalEvent.pageX) && !isUndefined(originalEvent.clientX)) {
3941
        const eventDoc = event.target.ownerDocument || document;
3942
        const doc = eventDoc.documentElement;
3943
        const body = eventDoc.body;
3944
        const mouseEvent = event;
3945
        mouseEvent.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
3946
        mouseEvent.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
3947
      }
3948
      return event;
3949
    };
3950
    const bindOnReady = (win, callback, eventUtils) => {
3951
      const doc = win.document, event = { type: 'ready' };
3952
      if (eventUtils.domLoaded) {
3953
        callback(event);
3954
        return;
3955
      }
3956
      const isDocReady = () => {
3957
        return doc.readyState === 'complete' || doc.readyState === 'interactive' && doc.body;
3958
      };
3959
      const readyHandler = () => {
3960
        removeEvent(win, 'DOMContentLoaded', readyHandler);
3961
        removeEvent(win, 'load', readyHandler);
3962
        if (!eventUtils.domLoaded) {
3963
          eventUtils.domLoaded = true;
3964
          callback(event);
3965
        }
3966
        win = null;
3967
      };
3968
      if (isDocReady()) {
3969
        readyHandler();
3970
      } else {
3971
        addEvent(win, 'DOMContentLoaded', readyHandler);
3972
      }
3973
      if (!eventUtils.domLoaded) {
3974
        addEvent(win, 'load', readyHandler);
3975
      }
3976
    };
3977
    class EventUtils {
3978
      constructor() {
3979
        this.domLoaded = false;
3980
        this.events = {};
3981
        this.count = 1;
3982
        this.expando = eventExpandoPrefix + (+new Date()).toString(32);
3983
        this.hasFocusIn = 'onfocusin' in document.documentElement;
3984
        this.count = 1;
3985
      }
3986
      bind(target, names, callback, scope) {
3987
        const self = this;
3988
        let callbackList;
3989
        const win = window;
3990
        const defaultNativeHandler = evt => {
3991
          self.executeHandlers(fix(evt || win.event), id);
3992
        };
3993
        if (!target || isText$a(target) || isComment(target)) {
3994
          return callback;
3995
        }
3996
        let id;
3997
        if (!target[self.expando]) {
3998
          id = self.count++;
3999
          target[self.expando] = id;
4000
          self.events[id] = {};
4001
        } else {
4002
          id = target[self.expando];
4003
        }
4004
        scope = scope || target;
4005
        const namesList = names.split(' ');
4006
        let i = namesList.length;
4007
        while (i--) {
4008
          let name = namesList[i];
4009
          let nativeHandler = defaultNativeHandler;
4010
          let capture = false;
4011
          let fakeName = false;
4012
          if (name === 'DOMContentLoaded') {
4013
            name = 'ready';
4014
          }
4015
          if (self.domLoaded && name === 'ready' && target.readyState === 'complete') {
4016
            callback.call(scope, fix({ type: name }));
4017
            continue;
4018
          }
4019
          if (!self.hasFocusIn && (name === 'focusin' || name === 'focusout')) {
4020
            capture = true;
4021
            fakeName = name === 'focusin' ? 'focus' : 'blur';
4022
            nativeHandler = evt => {
4023
              const event = fix(evt || win.event);
4024
              event.type = event.type === 'focus' ? 'focusin' : 'focusout';
4025
              self.executeHandlers(event, id);
4026
            };
4027
          }
4028
          callbackList = self.events[id][name];
4029
          if (!callbackList) {
4030
            self.events[id][name] = callbackList = [{
4031
                func: callback,
4032
                scope
4033
              }];
4034
            callbackList.fakeName = fakeName;
4035
            callbackList.capture = capture;
4036
            callbackList.nativeHandler = nativeHandler;
4037
            if (name === 'ready') {
4038
              bindOnReady(target, nativeHandler, self);
4039
            } else {
4040
              addEvent(target, fakeName || name, nativeHandler, capture);
4041
            }
4042
          } else {
4043
            if (name === 'ready' && self.domLoaded) {
4044
              callback(fix({ type: name }));
4045
            } else {
4046
              callbackList.push({
4047
                func: callback,
4048
                scope
4049
              });
4050
            }
4051
          }
4052
        }
4053
        target = callbackList = null;
4054
        return callback;
4055
      }
4056
      unbind(target, names, callback) {
4057
        if (!target || isText$a(target) || isComment(target)) {
4058
          return this;
4059
        }
4060
        const id = target[this.expando];
4061
        if (id) {
4062
          let eventMap = this.events[id];
4063
          if (names) {
4064
            const namesList = names.split(' ');
4065
            let i = namesList.length;
4066
            while (i--) {
4067
              const name = namesList[i];
4068
              const callbackList = eventMap[name];
4069
              if (callbackList) {
4070
                if (callback) {
4071
                  let ci = callbackList.length;
4072
                  while (ci--) {
4073
                    if (callbackList[ci].func === callback) {
4074
                      const nativeHandler = callbackList.nativeHandler;
4075
                      const fakeName = callbackList.fakeName, capture = callbackList.capture;
4076
                      const newCallbackList = callbackList.slice(0, ci).concat(callbackList.slice(ci + 1));
4077
                      newCallbackList.nativeHandler = nativeHandler;
4078
                      newCallbackList.fakeName = fakeName;
4079
                      newCallbackList.capture = capture;
4080
                      eventMap[name] = newCallbackList;
4081
                    }
4082
                  }
4083
                }
4084
                if (!callback || callbackList.length === 0) {
4085
                  delete eventMap[name];
4086
                  removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
4087
                }
4088
              }
4089
            }
4090
          } else {
4091
            each$d(eventMap, (callbackList, name) => {
4092
              removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture);
4093
            });
4094
            eventMap = {};
4095
          }
4096
          for (const name in eventMap) {
4097
            if (has$2(eventMap, name)) {
4098
              return this;
4099
            }
4100
          }
4101
          delete this.events[id];
4102
          try {
4103
            delete target[this.expando];
4104
          } catch (ex) {
4105
            target[this.expando] = null;
4106
          }
4107
        }
4108
        return this;
4109
      }
4110
      fire(target, name, args) {
4111
        return this.dispatch(target, name, args);
4112
      }
4113
      dispatch(target, name, args) {
4114
        if (!target || isText$a(target) || isComment(target)) {
4115
          return this;
4116
        }
4117
        const event = fix({
4118
          type: name,
4119
          target
4120
        }, args);
4121
        do {
4122
          const id = target[this.expando];
4123
          if (id) {
4124
            this.executeHandlers(event, id);
4125
          }
4126
          target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow;
4127
        } while (target && !event.isPropagationStopped());
4128
        return this;
4129
      }
4130
      clean(target) {
4131
        if (!target || isText$a(target) || isComment(target)) {
4132
          return this;
4133
        }
4134
        if (target[this.expando]) {
4135
          this.unbind(target);
4136
        }
4137
        if (!target.getElementsByTagName) {
4138
          target = target.document;
4139
        }
4140
        if (target && target.getElementsByTagName) {
4141
          this.unbind(target);
4142
          const children = target.getElementsByTagName('*');
4143
          let i = children.length;
4144
          while (i--) {
4145
            target = children[i];
4146
            if (target[this.expando]) {
4147
              this.unbind(target);
4148
            }
4149
          }
4150
        }
4151
        return this;
4152
      }
4153
      destroy() {
4154
        this.events = {};
4155
      }
4156
      cancel(e) {
4157
        if (e) {
4158
          e.preventDefault();
4159
          e.stopImmediatePropagation();
4160
        }
4161
        return false;
4162
      }
4163
      executeHandlers(evt, id) {
4164
        const container = this.events[id];
4165
        const callbackList = container && container[evt.type];
4166
        if (callbackList) {
4167
          for (let i = 0, l = callbackList.length; i < l; i++) {
4168
            const callback = callbackList[i];
4169
            if (callback && callback.func.call(callback.scope, evt) === false) {
4170
              evt.preventDefault();
4171
            }
4172
            if (evt.isImmediatePropagationStopped()) {
4173
              return;
4174
            }
4175
          }
4176
        }
4177
      }
4178
    }
4179
    EventUtils.Event = new EventUtils();
4180
 
4181
    const each$a = Tools.each;
4182
    const grep = Tools.grep;
4183
    const internalStyleName = 'data-mce-style';
4184
    const numericalCssMap = Tools.makeMap('fill-opacity font-weight line-height opacity orphans widows z-index zoom', ' ');
4185
    const legacySetAttribute = (elm, name, value) => {
4186
      if (isNullable(value) || value === '') {
4187
        remove$a(elm, name);
4188
      } else {
4189
        set$3(elm, name, value);
4190
      }
4191
    };
4192
    const camelCaseToHyphens = name => name.replace(/[A-Z]/g, v => '-' + v.toLowerCase());
4193
    const findNodeIndex = (node, normalized) => {
4194
      let idx = 0;
4195
      if (node) {
4196
        for (let lastNodeType = node.nodeType, tempNode = node.previousSibling; tempNode; tempNode = tempNode.previousSibling) {
4197
          const nodeType = tempNode.nodeType;
4198
          if (normalized && isText$a(tempNode)) {
4199
            if (nodeType === lastNodeType || !tempNode.data.length) {
4200
              continue;
4201
            }
4202
          }
4203
          idx++;
4204
          lastNodeType = nodeType;
4205
        }
4206
      }
4207
      return idx;
4208
    };
4209
    const updateInternalStyleAttr = (styles, elm) => {
4210
      const rawValue = get$9(elm, 'style');
4211
      const value = styles.serialize(styles.parse(rawValue), name(elm));
4212
      legacySetAttribute(elm, internalStyleName, value);
4213
    };
4214
    const convertStyleToString = (cssValue, cssName) => {
4215
      if (isNumber(cssValue)) {
4216
        return has$2(numericalCssMap, cssName) ? cssValue + '' : cssValue + 'px';
4217
      } else {
4218
        return cssValue;
4219
      }
4220
    };
4221
    const applyStyle$1 = ($elm, cssName, cssValue) => {
4222
      const normalizedName = camelCaseToHyphens(cssName);
4223
      if (isNullable(cssValue) || cssValue === '') {
4224
        remove$6($elm, normalizedName);
4225
      } else {
4226
        set$2($elm, normalizedName, convertStyleToString(cssValue, normalizedName));
4227
      }
4228
    };
4229
    const setupAttrHooks = (styles, settings, getContext) => {
4230
      const keepValues = settings.keep_values;
4231
      const keepUrlHook = {
4232
        set: (elm, value, name) => {
4233
          const sugarElm = SugarElement.fromDom(elm);
4234
          if (isFunction(settings.url_converter) && isNonNullable(value)) {
4235
            value = settings.url_converter.call(settings.url_converter_scope || getContext(), String(value), name, elm);
4236
          }
4237
          const internalName = 'data-mce-' + name;
4238
          legacySetAttribute(sugarElm, internalName, value);
4239
          legacySetAttribute(sugarElm, name, value);
4240
        },
4241
        get: (elm, name) => {
4242
          const sugarElm = SugarElement.fromDom(elm);
4243
          return get$9(sugarElm, 'data-mce-' + name) || get$9(sugarElm, name);
4244
        }
4245
      };
4246
      const attrHooks = {
4247
        style: {
4248
          set: (elm, value) => {
4249
            const sugarElm = SugarElement.fromDom(elm);
4250
            if (keepValues) {
4251
              legacySetAttribute(sugarElm, internalStyleName, value);
4252
            }
4253
            remove$a(sugarElm, 'style');
4254
            if (isString(value)) {
4255
              setAll(sugarElm, styles.parse(value));
4256
            }
4257
          },
4258
          get: elm => {
4259
            const sugarElm = SugarElement.fromDom(elm);
4260
            const value = get$9(sugarElm, internalStyleName) || get$9(sugarElm, 'style');
4261
            return styles.serialize(styles.parse(value), name(sugarElm));
4262
          }
4263
        }
4264
      };
4265
      if (keepValues) {
4266
        attrHooks.href = attrHooks.src = keepUrlHook;
4267
      }
4268
      return attrHooks;
4269
    };
4270
    const DOMUtils = (doc, settings = {}) => {
4271
      const addedStyles = {};
4272
      const win = window;
4273
      const files = {};
4274
      let counter = 0;
4275
      const stdMode = true;
4276
      const boxModel = true;
4277
      const styleSheetLoader = instance.forElement(SugarElement.fromDom(doc), {
4278
        contentCssCors: settings.contentCssCors,
4279
        referrerPolicy: settings.referrerPolicy
4280
      });
4281
      const boundEvents = [];
4282
      const schema = settings.schema ? settings.schema : Schema({});
4283
      const styles = Styles({
4284
        url_converter: settings.url_converter,
4285
        url_converter_scope: settings.url_converter_scope,
4286
        force_hex_color: settings.force_hex_color
4287
      }, settings.schema);
4288
      const events = settings.ownEvents ? new EventUtils() : EventUtils.Event;
4289
      const blockElementsMap = schema.getBlockElements();
4290
      const isBlock = node => {
4291
        if (isString(node)) {
4292
          return has$2(blockElementsMap, node);
4293
        } else {
4294
          return isElement$6(node) && (has$2(blockElementsMap, node.nodeName) || isTransparentBlock(schema, node));
4295
        }
4296
      };
4297
      const get = elm => elm && doc && isString(elm) ? doc.getElementById(elm) : elm;
4298
      const _get = elm => {
4299
        const value = get(elm);
4300
        return isNonNullable(value) ? SugarElement.fromDom(value) : null;
4301
      };
4302
      const getAttrib = (elm, name, defaultVal = '') => {
4303
        let value;
4304
        const $elm = _get(elm);
4305
        if (isNonNullable($elm) && isElement$7($elm)) {
4306
          const hook = attrHooks[name];
4307
          if (hook && hook.get) {
4308
            value = hook.get($elm.dom, name);
4309
          } else {
4310
            value = get$9($elm, name);
4311
          }
4312
        }
4313
        return isNonNullable(value) ? value : defaultVal;
4314
      };
4315
      const getAttribs = elm => {
4316
        const node = get(elm);
4317
        return isNullable(node) ? [] : node.attributes;
4318
      };
4319
      const setAttrib = (elm, name, value) => {
4320
        run(elm, e => {
4321
          if (isElement$6(e)) {
4322
            const $elm = SugarElement.fromDom(e);
4323
            const val = value === '' ? null : value;
4324
            const originalValue = get$9($elm, name);
4325
            const hook = attrHooks[name];
4326
            if (hook && hook.set) {
4327
              hook.set($elm.dom, val, name);
4328
            } else {
4329
              legacySetAttribute($elm, name, val);
4330
            }
4331
            if (originalValue !== val && settings.onSetAttrib) {
4332
              settings.onSetAttrib({
4333
                attrElm: $elm.dom,
4334
                attrName: name,
4335
                attrValue: val
4336
              });
4337
            }
4338
          }
4339
        });
4340
      };
4341
      const clone = (node, deep) => {
4342
        return node.cloneNode(deep);
4343
      };
4344
      const getRoot = () => settings.root_element || doc.body;
4345
      const getViewPort = argWin => {
4346
        const vp = getBounds(argWin);
4347
        return {
4348
          x: vp.x,
4349
          y: vp.y,
4350
          w: vp.width,
4351
          h: vp.height
4352
        };
4353
      };
4354
      const getPos$1 = (elm, rootElm) => getPos(doc.body, get(elm), rootElm);
4355
      const setStyle = (elm, name, value) => {
4356
        run(elm, e => {
4357
          const $elm = SugarElement.fromDom(e);
4358
          applyStyle$1($elm, name, value);
4359
          if (settings.update_styles) {
4360
            updateInternalStyleAttr(styles, $elm);
4361
          }
4362
        });
4363
      };
4364
      const setStyles = (elm, stylesArg) => {
4365
        run(elm, e => {
4366
          const $elm = SugarElement.fromDom(e);
4367
          each$d(stylesArg, (v, n) => {
4368
            applyStyle$1($elm, n, v);
4369
          });
4370
          if (settings.update_styles) {
4371
            updateInternalStyleAttr(styles, $elm);
4372
          }
4373
        });
4374
      };
4375
      const getStyle = (elm, name, computed) => {
4376
        const $elm = get(elm);
4377
        if (isNullable($elm) || !isHTMLElement($elm) && !isSVGElement($elm)) {
4378
          return undefined;
4379
        }
4380
        if (computed) {
4381
          return get$7(SugarElement.fromDom($elm), camelCaseToHyphens(name));
4382
        } else {
4383
          name = name.replace(/-(\D)/g, (a, b) => b.toUpperCase());
4384
          if (name === 'float') {
4385
            name = 'cssFloat';
4386
          }
4387
          return $elm.style ? $elm.style[name] : undefined;
4388
        }
4389
      };
4390
      const getSize = elm => {
4391
        const $elm = get(elm);
4392
        if (!$elm) {
4393
          return {
4394
            w: 0,
4395
            h: 0
4396
          };
4397
        }
4398
        let w = getStyle($elm, 'width');
4399
        let h = getStyle($elm, 'height');
4400
        if (!w || w.indexOf('px') === -1) {
4401
          w = '0';
4402
        }
4403
        if (!h || h.indexOf('px') === -1) {
4404
          h = '0';
4405
        }
4406
        return {
4407
          w: parseInt(w, 10) || $elm.offsetWidth || $elm.clientWidth,
4408
          h: parseInt(h, 10) || $elm.offsetHeight || $elm.clientHeight
4409
        };
4410
      };
4411
      const getRect = elm => {
4412
        const $elm = get(elm);
4413
        const pos = getPos$1($elm);
4414
        const size = getSize($elm);
4415
        return {
4416
          x: pos.x,
4417
          y: pos.y,
4418
          w: size.w,
4419
          h: size.h
4420
        };
4421
      };
4422
      const is = (elm, selector) => {
4423
        if (!elm) {
4424
          return false;
4425
        }
4426
        const elms = isArray$1(elm) ? elm : [elm];
4427
        return exists(elms, e => {
4428
          return is$1(SugarElement.fromDom(e), selector);
4429
        });
4430
      };
4431
      const getParents = (elm, selector, root, collect) => {
4432
        const result = [];
4433
        let node = get(elm);
4434
        collect = collect === undefined;
4435
        const resolvedRoot = root || (getRoot().nodeName !== 'BODY' ? getRoot().parentNode : null);
4436
        if (isString(selector)) {
4437
          if (selector === '*') {
4438
            selector = isElement$6;
4439
          } else {
4440
            const selectorVal = selector;
4441
            selector = node => is(node, selectorVal);
4442
          }
4443
        }
4444
        while (node) {
4445
          if (node === resolvedRoot || isNullable(node.nodeType) || isDocument$1(node) || isDocumentFragment(node)) {
4446
            break;
4447
          }
4448
          if (!selector || selector(node)) {
4449
            if (collect) {
4450
              result.push(node);
4451
            } else {
4452
              return [node];
4453
            }
4454
          }
4455
          node = node.parentNode;
4456
        }
4457
        return collect ? result : null;
4458
      };
4459
      const getParent = (node, selector, root) => {
4460
        const parents = getParents(node, selector, root, false);
4461
        return parents && parents.length > 0 ? parents[0] : null;
4462
      };
4463
      const _findSib = (node, selector, name) => {
4464
        let func = selector;
4465
        if (node) {
4466
          if (isString(selector)) {
4467
            func = node => {
4468
              return is(node, selector);
4469
            };
4470
          }
4471
          for (let tempNode = node[name]; tempNode; tempNode = tempNode[name]) {
4472
            if (isFunction(func) && func(tempNode)) {
4473
              return tempNode;
4474
            }
4475
          }
4476
        }
4477
        return null;
4478
      };
4479
      const getNext = (node, selector) => _findSib(node, selector, 'nextSibling');
4480
      const getPrev = (node, selector) => _findSib(node, selector, 'previousSibling');
4481
      const isParentNode = node => isFunction(node.querySelectorAll);
4482
      const select = (selector, scope) => {
4483
        var _a, _b;
4484
        const elm = (_b = (_a = get(scope)) !== null && _a !== void 0 ? _a : settings.root_element) !== null && _b !== void 0 ? _b : doc;
4485
        return isParentNode(elm) ? from(elm.querySelectorAll(selector)) : [];
4486
      };
4487
      const run = function (elm, func, scope) {
4488
        const context = scope !== null && scope !== void 0 ? scope : this;
4489
        if (isArray$1(elm)) {
4490
          const result = [];
4491
          each$a(elm, (e, i) => {
4492
            const node = get(e);
4493
            if (node) {
4494
              result.push(func.call(context, node, i));
4495
            }
4496
          });
4497
          return result;
4498
        } else {
4499
          const node = get(elm);
4500
          return !node ? false : func.call(context, node);
4501
        }
4502
      };
4503
      const setAttribs = (elm, attrs) => {
4504
        run(elm, $elm => {
4505
          each$d(attrs, (value, name) => {
4506
            setAttrib($elm, name, value);
4507
          });
4508
        });
4509
      };
4510
      const setHTML = (elm, html) => {
4511
        run(elm, e => {
4512
          const $elm = SugarElement.fromDom(e);
4513
          set$1($elm, html);
4514
        });
4515
      };
4516
      const add = (parentElm, name, attrs, html, create) => run(parentElm, parentElm => {
4517
        const newElm = isString(name) ? doc.createElement(name) : name;
4518
        if (isNonNullable(attrs)) {
4519
          setAttribs(newElm, attrs);
4520
        }
4521
        if (html) {
4522
          if (!isString(html) && html.nodeType) {
4523
            newElm.appendChild(html);
4524
          } else if (isString(html)) {
4525
            setHTML(newElm, html);
4526
          }
4527
        }
4528
        return !create ? parentElm.appendChild(newElm) : newElm;
4529
      });
4530
      const create = (name, attrs, html) => add(doc.createElement(name), name, attrs, html, true);
4531
      const decode = Entities.decode;
4532
      const encode = Entities.encodeAllRaw;
4533
      const createHTML = (name, attrs, html = '') => {
4534
        let outHtml = '<' + name;
4535
        for (const key in attrs) {
4536
          if (hasNonNullableKey(attrs, key)) {
4537
            outHtml += ' ' + key + '="' + encode(attrs[key]) + '"';
4538
          }
4539
        }
4540
        if (isEmpty$3(html) && has$2(schema.getVoidElements(), name)) {
4541
          return outHtml + ' />';
4542
        } else {
4543
          return outHtml + '>' + html + '</' + name + '>';
4544
        }
4545
      };
4546
      const createFragment = html => {
4547
        const container = doc.createElement('div');
4548
        const frag = doc.createDocumentFragment();
4549
        frag.appendChild(container);
4550
        if (html) {
4551
          container.innerHTML = html;
4552
        }
4553
        let node;
4554
        while (node = container.firstChild) {
4555
          frag.appendChild(node);
4556
        }
4557
        frag.removeChild(container);
4558
        return frag;
4559
      };
4560
      const remove = (node, keepChildren) => {
4561
        return run(node, n => {
4562
          const $node = SugarElement.fromDom(n);
4563
          if (keepChildren) {
4564
            each$e(children$1($node), child => {
4565
              if (isText$b(child) && child.dom.length === 0) {
4566
                remove$5(child);
4567
              } else {
4568
                before$3($node, child);
4569
              }
4570
            });
4571
          }
4572
          remove$5($node);
4573
          return $node.dom;
4574
        });
4575
      };
4576
      const removeAllAttribs = e => run(e, e => {
4577
        const attrs = e.attributes;
4578
        for (let i = attrs.length - 1; i >= 0; i--) {
4579
          e.removeAttributeNode(attrs.item(i));
4580
        }
4581
      });
4582
      const parseStyle = cssText => styles.parse(cssText);
4583
      const serializeStyle = (stylesArg, name) => styles.serialize(stylesArg, name);
4584
      const addStyle = cssText => {
4585
        if (self !== DOMUtils.DOM && doc === document) {
4586
          if (addedStyles[cssText]) {
4587
            return;
4588
          }
4589
          addedStyles[cssText] = true;
4590
        }
4591
        let styleElm = doc.getElementById('mceDefaultStyles');
4592
        if (!styleElm) {
4593
          styleElm = doc.createElement('style');
4594
          styleElm.id = 'mceDefaultStyles';
4595
          styleElm.type = 'text/css';
4596
          const head = doc.head;
4597
          if (head.firstChild) {
4598
            head.insertBefore(styleElm, head.firstChild);
4599
          } else {
4600
            head.appendChild(styleElm);
4601
          }
4602
        }
4603
        if (styleElm.styleSheet) {
4604
          styleElm.styleSheet.cssText += cssText;
4605
        } else {
4606
          styleElm.appendChild(doc.createTextNode(cssText));
4607
        }
4608
      };
4609
      const loadCSS = urls => {
4610
        if (!urls) {
4611
          urls = '';
4612
        }
4613
        each$e(urls.split(','), url => {
4614
          files[url] = true;
4615
          styleSheetLoader.load(url).catch(noop);
4616
        });
4617
      };
4618
      const toggleClass = (elm, cls, state) => {
4619
        run(elm, e => {
4620
          if (isElement$6(e)) {
4621
            const $elm = SugarElement.fromDom(e);
4622
            const classes = cls.split(' ');
4623
            each$e(classes, c => {
4624
              if (isNonNullable(state)) {
4625
                const fn = state ? add$2 : remove$7;
4626
                fn($elm, c);
4627
              } else {
4628
                toggle$1($elm, c);
4629
              }
4630
            });
4631
          }
4632
        });
4633
      };
4634
      const addClass = (elm, cls) => {
4635
        toggleClass(elm, cls, true);
4636
      };
4637
      const removeClass = (elm, cls) => {
4638
        toggleClass(elm, cls, false);
4639
      };
4640
      const hasClass = (elm, cls) => {
4641
        const $elm = _get(elm);
4642
        const classes = cls.split(' ');
4643
        return isNonNullable($elm) && forall(classes, c => has($elm, c));
4644
      };
4645
      const show = elm => {
4646
        run(elm, e => remove$6(SugarElement.fromDom(e), 'display'));
4647
      };
4648
      const hide = elm => {
4649
        run(elm, e => set$2(SugarElement.fromDom(e), 'display', 'none'));
4650
      };
4651
      const isHidden = elm => {
4652
        const $elm = _get(elm);
4653
        return isNonNullable($elm) && is$2(getRaw($elm, 'display'), 'none');
4654
      };
4655
      const uniqueId = prefix => (!prefix ? 'mce_' : prefix) + counter++;
4656
      const getOuterHTML = elm => {
4657
        const $elm = _get(elm);
4658
        if (isNonNullable($elm)) {
4659
          return isElement$6($elm.dom) ? $elm.dom.outerHTML : getOuter($elm);
4660
        } else {
4661
          return '';
4662
        }
4663
      };
4664
      const setOuterHTML = (elm, html) => {
4665
        run(elm, $elm => {
4666
          if (isElement$6($elm)) {
4667
            $elm.outerHTML = html;
4668
          }
4669
        });
4670
      };
4671
      const insertAfter = (node, reference) => {
4672
        const referenceNode = get(reference);
4673
        return run(node, node => {
4674
          const parent = referenceNode === null || referenceNode === void 0 ? void 0 : referenceNode.parentNode;
4675
          const nextSibling = referenceNode === null || referenceNode === void 0 ? void 0 : referenceNode.nextSibling;
4676
          if (parent) {
4677
            if (nextSibling) {
4678
              parent.insertBefore(node, nextSibling);
4679
            } else {
4680
              parent.appendChild(node);
4681
            }
4682
          }
4683
          return node;
4684
        });
4685
      };
4686
      const replace = (newElm, oldElm, keepChildren) => run(oldElm, elm => {
4687
        var _a;
4688
        const replacee = isArray$1(oldElm) ? newElm.cloneNode(true) : newElm;
4689
        if (keepChildren) {
4690
          each$a(grep(elm.childNodes), node => {
4691
            replacee.appendChild(node);
4692
          });
4693
        }
4694
        (_a = elm.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(replacee, elm);
4695
        return elm;
4696
      });
4697
      const rename = (elm, name) => {
4698
        if (elm.nodeName !== name.toUpperCase()) {
4699
          const newElm = create(name);
4700
          each$a(getAttribs(elm), attrNode => {
4701
            setAttrib(newElm, attrNode.nodeName, getAttrib(elm, attrNode.nodeName));
4702
          });
4703
          replace(newElm, elm, true);
4704
          return newElm;
4705
        } else {
4706
          return elm;
4707
        }
4708
      };
4709
      const findCommonAncestor = (a, b) => {
4710
        let ps = a;
4711
        while (ps) {
4712
          let pe = b;
4713
          while (pe && ps !== pe) {
4714
            pe = pe.parentNode;
4715
          }
4716
          if (ps === pe) {
4717
            break;
4718
          }
4719
          ps = ps.parentNode;
4720
        }
4721
        if (!ps && a.ownerDocument) {
4722
          return a.ownerDocument.documentElement;
4723
        } else {
4724
          return ps;
4725
        }
4726
      };
4727
      const isNonEmptyElement = node => {
4728
        if (isElement$6(node)) {
4729
          const isNamedAnchor = node.nodeName.toLowerCase() === 'a' && !getAttrib(node, 'href') && getAttrib(node, 'id');
4730
          if (getAttrib(node, 'name') || getAttrib(node, 'data-mce-bookmark') || isNamedAnchor) {
4731
            return true;
4732
          }
4733
        }
4734
        return false;
4735
      };
4736
      const isEmpty = (node, elements, options) => {
4737
        let brCount = 0;
4738
        if (isNonEmptyElement(node)) {
4739
          return false;
4740
        }
4741
        const firstChild = node.firstChild;
4742
        if (firstChild) {
4743
          const walker = new DomTreeWalker(firstChild, node);
4744
          const whitespaceElements = schema ? schema.getWhitespaceElements() : {};
4745
          const nonEmptyElements = elements || (schema ? schema.getNonEmptyElements() : null);
4746
          let tempNode = firstChild;
4747
          do {
4748
            if (isElement$6(tempNode)) {
4749
              const bogusVal = tempNode.getAttribute('data-mce-bogus');
4750
              if (bogusVal) {
4751
                tempNode = walker.next(bogusVal === 'all');
4752
                continue;
4753
              }
4754
              const name = tempNode.nodeName.toLowerCase();
4755
              if (nonEmptyElements && nonEmptyElements[name]) {
4756
                if (name === 'br') {
4757
                  brCount++;
4758
                  tempNode = walker.next();
4759
                  continue;
4760
                }
4761
                return false;
4762
              }
4763
              if (isNonEmptyElement(tempNode)) {
4764
                return false;
4765
              }
4766
            }
4767
            if (isComment(tempNode)) {
4768
              return false;
4769
            }
4770
            if (isText$a(tempNode) && !isWhitespaceText(tempNode.data) && (!(options === null || options === void 0 ? void 0 : options.includeZwsp) || !isZwsp(tempNode.data))) {
4771
              return false;
4772
            }
4773
            if (isText$a(tempNode) && tempNode.parentNode && whitespaceElements[tempNode.parentNode.nodeName] && isWhitespaceText(tempNode.data)) {
4774
              return false;
4775
            }
4776
            tempNode = walker.next();
4777
          } while (tempNode);
4778
        }
4779
        return brCount <= 1;
4780
      };
4781
      const createRng = () => doc.createRange();
4782
      const split = (parentElm, splitElm, replacementElm) => {
4783
        let range = createRng();
4784
        let beforeFragment;
4785
        let afterFragment;
4786
        if (parentElm && splitElm && parentElm.parentNode && splitElm.parentNode) {
4787
          const parentNode = parentElm.parentNode;
4788
          range.setStart(parentNode, findNodeIndex(parentElm));
4789
          range.setEnd(splitElm.parentNode, findNodeIndex(splitElm));
4790
          beforeFragment = range.extractContents();
4791
          range = createRng();
4792
          range.setStart(splitElm.parentNode, findNodeIndex(splitElm) + 1);
4793
          range.setEnd(parentNode, findNodeIndex(parentElm) + 1);
4794
          afterFragment = range.extractContents();
4795
          parentNode.insertBefore(trimNode(self, beforeFragment, schema), parentElm);
4796
          if (replacementElm) {
4797
            parentNode.insertBefore(replacementElm, parentElm);
4798
          } else {
4799
            parentNode.insertBefore(splitElm, parentElm);
4800
          }
4801
          parentNode.insertBefore(trimNode(self, afterFragment, schema), parentElm);
4802
          remove(parentElm);
4803
          return replacementElm || splitElm;
4804
        } else {
4805
          return undefined;
4806
        }
4807
      };
4808
      const bind = (target, name, func, scope) => {
4809
        if (isArray$1(target)) {
4810
          let i = target.length;
4811
          const rv = [];
4812
          while (i--) {
4813
            rv[i] = bind(target[i], name, func, scope);
4814
          }
4815
          return rv;
4816
        } else {
4817
          if (settings.collect && (target === doc || target === win)) {
4818
            boundEvents.push([
4819
              target,
4820
              name,
4821
              func,
4822
              scope
4823
            ]);
4824
          }
4825
          return events.bind(target, name, func, scope || self);
4826
        }
4827
      };
4828
      const unbind = (target, name, func) => {
4829
        if (isArray$1(target)) {
4830
          let i = target.length;
4831
          const rv = [];
4832
          while (i--) {
4833
            rv[i] = unbind(target[i], name, func);
4834
          }
4835
          return rv;
4836
        } else {
4837
          if (boundEvents.length > 0 && (target === doc || target === win)) {
4838
            let i = boundEvents.length;
4839
            while (i--) {
4840
              const [boundTarget, boundName, boundFunc] = boundEvents[i];
4841
              if (target === boundTarget && (!name || name === boundName) && (!func || func === boundFunc)) {
4842
                events.unbind(boundTarget, boundName, boundFunc);
4843
              }
4844
            }
4845
          }
4846
          return events.unbind(target, name, func);
4847
        }
4848
      };
4849
      const dispatch = (target, name, evt) => events.dispatch(target, name, evt);
4850
      const fire = (target, name, evt) => events.dispatch(target, name, evt);
4851
      const getContentEditable = node => {
4852
        if (node && isHTMLElement(node)) {
4853
          const contentEditable = node.getAttribute('data-mce-contenteditable');
4854
          if (contentEditable && contentEditable !== 'inherit') {
4855
            return contentEditable;
4856
          }
4857
          return node.contentEditable !== 'inherit' ? node.contentEditable : null;
4858
        } else {
4859
          return null;
4860
        }
4861
      };
4862
      const getContentEditableParent = node => {
4863
        const root = getRoot();
4864
        let state = null;
4865
        for (let tempNode = node; tempNode && tempNode !== root; tempNode = tempNode.parentNode) {
4866
          state = getContentEditable(tempNode);
4867
          if (state !== null) {
4868
            break;
4869
          }
4870
        }
4871
        return state;
4872
      };
4873
      const isEditable = node => {
4874
        if (isNonNullable(node)) {
4875
          const scope = isElement$6(node) ? node : node.parentElement;
4876
          return isNonNullable(scope) && isHTMLElement(scope) && isEditable$2(SugarElement.fromDom(scope));
4877
        } else {
4878
          return false;
4879
        }
4880
      };
4881
      const destroy = () => {
4882
        if (boundEvents.length > 0) {
4883
          let i = boundEvents.length;
4884
          while (i--) {
4885
            const [boundTarget, boundName, boundFunc] = boundEvents[i];
4886
            events.unbind(boundTarget, boundName, boundFunc);
4887
          }
4888
        }
4889
        each$d(files, (_, url) => {
4890
          styleSheetLoader.unload(url);
4891
          delete files[url];
4892
        });
4893
      };
4894
      const isChildOf = (node, parent) => {
4895
        return node === parent || parent.contains(node);
4896
      };
4897
      const dumpRng = r => 'startContainer: ' + r.startContainer.nodeName + ', startOffset: ' + r.startOffset + ', endContainer: ' + r.endContainer.nodeName + ', endOffset: ' + r.endOffset;
4898
      const self = {
4899
        doc,
4900
        settings,
4901
        win,
4902
        files,
4903
        stdMode,
4904
        boxModel,
4905
        styleSheetLoader,
4906
        boundEvents,
4907
        styles,
4908
        schema,
4909
        events,
4910
        isBlock: isBlock,
4911
        root: null,
4912
        clone,
4913
        getRoot,
4914
        getViewPort,
4915
        getRect,
4916
        getSize,
4917
        getParent,
4918
        getParents: getParents,
4919
        get,
4920
        getNext,
4921
        getPrev,
4922
        select,
4923
        is,
4924
        add,
4925
        create,
4926
        createHTML,
4927
        createFragment,
4928
        remove,
4929
        setStyle,
4930
        getStyle: getStyle,
4931
        setStyles,
4932
        removeAllAttribs,
4933
        setAttrib,
4934
        setAttribs,
4935
        getAttrib,
4936
        getPos: getPos$1,
4937
        parseStyle,
4938
        serializeStyle,
4939
        addStyle,
4940
        loadCSS,
4941
        addClass,
4942
        removeClass,
4943
        hasClass,
4944
        toggleClass,
4945
        show,
4946
        hide,
4947
        isHidden,
4948
        uniqueId,
4949
        setHTML,
4950
        getOuterHTML,
4951
        setOuterHTML,
4952
        decode,
4953
        encode,
4954
        insertAfter,
4955
        replace,
4956
        rename,
4957
        findCommonAncestor,
4958
        run,
4959
        getAttribs,
4960
        isEmpty,
4961
        createRng,
4962
        nodeIndex: findNodeIndex,
4963
        split,
4964
        bind: bind,
4965
        unbind: unbind,
4966
        fire,
4967
        dispatch,
4968
        getContentEditable,
4969
        getContentEditableParent,
4970
        isEditable,
4971
        destroy,
4972
        isChildOf,
4973
        dumpRng
4974
      };
4975
      const attrHooks = setupAttrHooks(styles, settings, constant(self));
4976
      return self;
4977
    };
4978
    DOMUtils.DOM = DOMUtils(document);
4979
    DOMUtils.nodeIndex = findNodeIndex;
4980
 
4981
    const DOM$b = DOMUtils.DOM;
4982
    const QUEUED = 0;
4983
    const LOADING = 1;
4984
    const LOADED = 2;
4985
    const FAILED = 3;
4986
    class ScriptLoader {
4987
      constructor(settings = {}) {
4988
        this.states = {};
4989
        this.queue = [];
4990
        this.scriptLoadedCallbacks = {};
4991
        this.queueLoadedCallbacks = [];
4992
        this.loading = false;
4993
        this.settings = settings;
4994
      }
4995
      _setReferrerPolicy(referrerPolicy) {
4996
        this.settings.referrerPolicy = referrerPolicy;
4997
      }
4998
      loadScript(url) {
4999
        return new Promise((resolve, reject) => {
5000
          const dom = DOM$b;
5001
          let elm;
5002
          const cleanup = () => {
5003
            dom.remove(id);
5004
            if (elm) {
5005
              elm.onerror = elm.onload = elm = null;
5006
            }
5007
          };
5008
          const done = () => {
5009
            cleanup();
5010
            resolve();
5011
          };
5012
          const error = () => {
5013
            cleanup();
5014
            reject('Failed to load script: ' + url);
5015
          };
5016
          const id = dom.uniqueId();
5017
          elm = document.createElement('script');
5018
          elm.id = id;
5019
          elm.type = 'text/javascript';
5020
          elm.src = Tools._addCacheSuffix(url);
5021
          if (this.settings.referrerPolicy) {
5022
            dom.setAttrib(elm, 'referrerpolicy', this.settings.referrerPolicy);
5023
          }
5024
          elm.onload = done;
5025
          elm.onerror = error;
5026
          (document.getElementsByTagName('head')[0] || document.body).appendChild(elm);
5027
        });
5028
      }
5029
      isDone(url) {
5030
        return this.states[url] === LOADED;
5031
      }
5032
      markDone(url) {
5033
        this.states[url] = LOADED;
5034
      }
5035
      add(url) {
5036
        const self = this;
5037
        self.queue.push(url);
5038
        const state = self.states[url];
5039
        if (state === undefined) {
5040
          self.states[url] = QUEUED;
5041
        }
5042
        return new Promise((resolve, reject) => {
5043
          if (!self.scriptLoadedCallbacks[url]) {
5044
            self.scriptLoadedCallbacks[url] = [];
5045
          }
5046
          self.scriptLoadedCallbacks[url].push({
5047
            resolve,
5048
            reject
5049
          });
5050
        });
5051
      }
5052
      load(url) {
5053
        return this.add(url);
5054
      }
5055
      remove(url) {
5056
        delete this.states[url];
5057
        delete this.scriptLoadedCallbacks[url];
5058
      }
5059
      loadQueue() {
5060
        const queue = this.queue;
5061
        this.queue = [];
5062
        return this.loadScripts(queue);
5063
      }
5064
      loadScripts(scripts) {
5065
        const self = this;
5066
        const execCallbacks = (name, url) => {
5067
          get$a(self.scriptLoadedCallbacks, url).each(callbacks => {
5068
            each$e(callbacks, callback => callback[name](url));
5069
          });
5070
          delete self.scriptLoadedCallbacks[url];
5071
        };
5072
        const processResults = results => {
5073
          const failures = filter$5(results, result => result.status === 'rejected');
5074
          if (failures.length > 0) {
5075
            return Promise.reject(bind$3(failures, ({reason}) => isArray$1(reason) ? reason : [reason]));
5076
          } else {
5077
            return Promise.resolve();
5078
          }
5079
        };
5080
        const load = urls => Promise.allSettled(map$3(urls, url => {
5081
          if (self.states[url] === LOADED) {
5082
            execCallbacks('resolve', url);
5083
            return Promise.resolve();
5084
          } else if (self.states[url] === FAILED) {
5085
            execCallbacks('reject', url);
5086
            return Promise.reject(url);
5087
          } else {
5088
            self.states[url] = LOADING;
5089
            return self.loadScript(url).then(() => {
5090
              self.states[url] = LOADED;
5091
              execCallbacks('resolve', url);
5092
              const queue = self.queue;
5093
              if (queue.length > 0) {
5094
                self.queue = [];
5095
                return load(queue).then(processResults);
5096
              } else {
5097
                return Promise.resolve();
5098
              }
5099
            }, () => {
5100
              self.states[url] = FAILED;
5101
              execCallbacks('reject', url);
5102
              return Promise.reject(url);
5103
            });
5104
          }
5105
        }));
5106
        const processQueue = urls => {
5107
          self.loading = true;
5108
          return load(urls).then(results => {
5109
            self.loading = false;
5110
            const nextQueuedItem = self.queueLoadedCallbacks.shift();
5111
            Optional.from(nextQueuedItem).each(call);
5112
            return processResults(results);
5113
          });
5114
        };
5115
        const uniqueScripts = stringArray(scripts);
5116
        if (self.loading) {
5117
          return new Promise((resolve, reject) => {
5118
            self.queueLoadedCallbacks.push(() => {
5119
              processQueue(uniqueScripts).then(resolve, reject);
5120
            });
5121
          });
5122
        } else {
5123
          return processQueue(uniqueScripts);
5124
        }
5125
      }
5126
    }
5127
    ScriptLoader.ScriptLoader = new ScriptLoader();
5128
 
5129
    const Cell = initial => {
5130
      let value = initial;
5131
      const get = () => {
5132
        return value;
5133
      };
5134
      const set = v => {
5135
        value = v;
5136
      };
5137
      return {
5138
        get,
5139
        set
5140
      };
5141
    };
5142
 
5143
    const isDuplicated = (items, item) => {
5144
      const firstIndex = items.indexOf(item);
5145
      return firstIndex !== -1 && items.indexOf(item, firstIndex + 1) > firstIndex;
5146
    };
5147
    const isRaw = str => isObject(str) && has$2(str, 'raw');
5148
    const isTokenised = str => isArray$1(str) && str.length > 1;
5149
    const data = {};
5150
    const currentCode = Cell('en');
5151
    const getLanguageData = () => get$a(data, currentCode.get());
5152
    const getData$1 = () => map$2(data, value => ({ ...value }));
5153
    const setCode = newCode => {
5154
      if (newCode) {
5155
        currentCode.set(newCode);
5156
      }
5157
    };
5158
    const getCode = () => currentCode.get();
5159
    const add$1 = (code, items) => {
5160
      let langData = data[code];
5161
      if (!langData) {
5162
        data[code] = langData = {};
5163
      }
5164
      const lcNames = map$3(keys(items), name => name.toLowerCase());
5165
      each$d(items, (translation, name) => {
5166
        const lcName = name.toLowerCase();
5167
        if (lcName !== name && isDuplicated(lcNames, lcName)) {
5168
          if (!has$2(items, lcName)) {
5169
            langData[lcName] = translation;
5170
          }
5171
          langData[name] = translation;
5172
        } else {
5173
          langData[lcName] = translation;
5174
        }
5175
      });
5176
    };
5177
    const translate = text => {
5178
      const langData = getLanguageData().getOr({});
5179
      const toString = obj => {
5180
        if (isFunction(obj)) {
5181
          return Object.prototype.toString.call(obj);
5182
        }
5183
        return !isEmpty(obj) ? '' + obj : '';
5184
      };
5185
      const isEmpty = text => text === '' || text === null || text === undefined;
5186
      const getLangData = text => {
5187
        const textStr = toString(text);
5188
        return has$2(langData, textStr) ? toString(langData[textStr]) : get$a(langData, textStr.toLowerCase()).map(toString).getOr(textStr);
5189
      };
5190
      const removeContext = str => str.replace(/{context:\w+}$/, '');
5191
      if (isEmpty(text)) {
5192
        return '';
5193
      }
5194
      if (isRaw(text)) {
5195
        return toString(text.raw);
5196
      }
5197
      if (isTokenised(text)) {
5198
        const values = text.slice(1);
5199
        const substitued = getLangData(text[0]).replace(/\{([0-9]+)\}/g, ($1, $2) => has$2(values, $2) ? toString(values[$2]) : $1);
5200
        return removeContext(substitued);
5201
      }
5202
      return removeContext(getLangData(text));
5203
    };
5204
    const isRtl$1 = () => getLanguageData().bind(items => get$a(items, '_dir')).exists(dir => dir === 'rtl');
5205
    const hasCode = code => has$2(data, code);
5206
    const I18n = {
5207
      getData: getData$1,
5208
      setCode,
5209
      getCode,
5210
      add: add$1,
5211
      translate,
5212
      isRtl: isRtl$1,
5213
      hasCode
5214
    };
5215
 
5216
    const AddOnManager = () => {
5217
      const items = [];
5218
      const urls = {};
5219
      const lookup = {};
5220
      const _listeners = [];
5221
      const runListeners = (name, state) => {
5222
        const matchedListeners = filter$5(_listeners, listener => listener.name === name && listener.state === state);
5223
        each$e(matchedListeners, listener => listener.resolve());
5224
      };
5225
      const isLoaded = name => has$2(urls, name);
5226
      const isAdded = name => has$2(lookup, name);
5227
      const get = name => {
5228
        if (lookup[name]) {
5229
          return lookup[name].instance;
5230
        }
5231
        return undefined;
5232
      };
5233
      const loadLanguagePack = (name, languages) => {
5234
        const language = I18n.getCode();
5235
        const wrappedLanguages = ',' + (languages || '') + ',';
5236
        if (!language || languages && wrappedLanguages.indexOf(',' + language + ',') === -1) {
5237
          return;
5238
        }
5239
        ScriptLoader.ScriptLoader.add(urls[name] + '/langs/' + language + '.js');
5240
      };
5241
      const requireLangPack = (name, languages) => {
5242
        if (AddOnManager.languageLoad !== false) {
5243
          if (isLoaded(name)) {
5244
            loadLanguagePack(name, languages);
5245
          } else {
5246
            waitFor(name, 'loaded').then(() => loadLanguagePack(name, languages));
5247
          }
5248
        }
5249
      };
5250
      const add = (id, addOn) => {
5251
        items.push(addOn);
5252
        lookup[id] = { instance: addOn };
5253
        runListeners(id, 'added');
5254
        return addOn;
5255
      };
5256
      const remove = name => {
5257
        delete urls[name];
5258
        delete lookup[name];
5259
      };
5260
      const createUrl = (baseUrl, dep) => {
5261
        if (isString(dep)) {
5262
          return isString(baseUrl) ? {
5263
            prefix: '',
5264
            resource: dep,
5265
            suffix: ''
5266
          } : {
5267
            prefix: baseUrl.prefix,
5268
            resource: dep,
5269
            suffix: baseUrl.suffix
5270
          };
5271
        } else {
5272
          return dep;
5273
        }
5274
      };
5275
      const load = (name, addOnUrl) => {
5276
        if (urls[name]) {
5277
          return Promise.resolve();
5278
        }
5279
        let urlString = isString(addOnUrl) ? addOnUrl : addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
5280
        if (urlString.indexOf('/') !== 0 && urlString.indexOf('://') === -1) {
5281
          urlString = AddOnManager.baseURL + '/' + urlString;
5282
        }
5283
        urls[name] = urlString.substring(0, urlString.lastIndexOf('/'));
5284
        const done = () => {
5285
          runListeners(name, 'loaded');
5286
          return Promise.resolve();
5287
        };
5288
        if (lookup[name]) {
5289
          return done();
5290
        } else {
5291
          return ScriptLoader.ScriptLoader.add(urlString).then(done);
5292
        }
5293
      };
5294
      const waitFor = (name, state = 'added') => {
5295
        if (state === 'added' && isAdded(name)) {
5296
          return Promise.resolve();
5297
        } else if (state === 'loaded' && isLoaded(name)) {
5298
          return Promise.resolve();
5299
        } else {
5300
          return new Promise(resolve => {
5301
            _listeners.push({
5302
              name,
5303
              state,
5304
              resolve
5305
            });
5306
          });
5307
        }
5308
      };
5309
      return {
5310
        items,
5311
        urls,
5312
        lookup,
5313
        get,
5314
        requireLangPack,
5315
        add,
5316
        remove,
5317
        createUrl,
5318
        load,
5319
        waitFor
5320
      };
5321
    };
5322
    AddOnManager.languageLoad = true;
5323
    AddOnManager.baseURL = '';
5324
    AddOnManager.PluginManager = AddOnManager();
5325
    AddOnManager.ThemeManager = AddOnManager();
5326
    AddOnManager.ModelManager = AddOnManager();
5327
 
5328
    const singleton = doRevoke => {
5329
      const subject = Cell(Optional.none());
5330
      const revoke = () => subject.get().each(doRevoke);
5331
      const clear = () => {
5332
        revoke();
5333
        subject.set(Optional.none());
5334
      };
5335
      const isSet = () => subject.get().isSome();
5336
      const get = () => subject.get();
5337
      const set = s => {
5338
        revoke();
5339
        subject.set(Optional.some(s));
5340
      };
5341
      return {
5342
        clear,
5343
        isSet,
5344
        get,
5345
        set
5346
      };
5347
    };
5348
    const repeatable = delay => {
5349
      const intervalId = Cell(Optional.none());
5350
      const revoke = () => intervalId.get().each(id => clearInterval(id));
5351
      const clear = () => {
5352
        revoke();
5353
        intervalId.set(Optional.none());
5354
      };
5355
      const isSet = () => intervalId.get().isSome();
5356
      const get = () => intervalId.get();
5357
      const set = functionToRepeat => {
5358
        revoke();
5359
        intervalId.set(Optional.some(setInterval(functionToRepeat, delay)));
5360
      };
5361
      return {
5362
        clear,
5363
        isSet,
5364
        get,
5365
        set
5366
      };
5367
    };
5368
    const value$2 = () => {
5369
      const subject = singleton(noop);
5370
      const on = f => subject.get().each(f);
5371
      return {
5372
        ...subject,
5373
        on
5374
      };
5375
    };
5376
 
5377
    const first$1 = (fn, rate) => {
5378
      let timer = null;
5379
      const cancel = () => {
5380
        if (!isNull(timer)) {
5381
          clearTimeout(timer);
5382
          timer = null;
5383
        }
5384
      };
5385
      const throttle = (...args) => {
5386
        if (isNull(timer)) {
5387
          timer = setTimeout(() => {
5388
            timer = null;
5389
            fn.apply(null, args);
5390
          }, rate);
5391
        }
5392
      };
5393
      return {
5394
        cancel,
5395
        throttle
5396
      };
5397
    };
5398
    const last$1 = (fn, rate) => {
5399
      let timer = null;
5400
      const cancel = () => {
5401
        if (!isNull(timer)) {
5402
          clearTimeout(timer);
5403
          timer = null;
5404
        }
5405
      };
5406
      const throttle = (...args) => {
5407
        cancel();
5408
        timer = setTimeout(() => {
5409
          timer = null;
5410
          fn.apply(null, args);
5411
        }, rate);
5412
      };
5413
      return {
5414
        cancel,
5415
        throttle
5416
      };
5417
    };
5418
 
5419
    const annotation = constant('mce-annotation');
5420
    const dataAnnotation = constant('data-mce-annotation');
5421
    const dataAnnotationId = constant('data-mce-annotation-uid');
5422
    const dataAnnotationActive = constant('data-mce-annotation-active');
5423
    const dataAnnotationClasses = constant('data-mce-annotation-classes');
5424
    const dataAnnotationAttributes = constant('data-mce-annotation-attrs');
5425
 
5426
    const isRoot$1 = root => node => eq(node, root);
5427
    const identify = (editor, annotationName) => {
5428
      const rng = editor.selection.getRng();
5429
      const start = SugarElement.fromDom(rng.startContainer);
5430
      const root = SugarElement.fromDom(editor.getBody());
5431
      const selector = annotationName.fold(() => '.' + annotation(), an => `[${ dataAnnotation() }="${ an }"]`);
5432
      const newStart = child$1(start, rng.startOffset).getOr(start);
5433
      const closest = closest$3(newStart, selector, isRoot$1(root));
5434
      return closest.bind(c => getOpt(c, `${ dataAnnotationId() }`).bind(uid => getOpt(c, `${ dataAnnotation() }`).map(name => {
5435
        const elements = findMarkers(editor, uid);
5436
        return {
5437
          uid,
5438
          name,
5439
          elements
5440
        };
5441
      })));
5442
    };
5443
    const isAnnotation = elem => isElement$7(elem) && has(elem, annotation());
5444
    const isBogusElement = (elem, root) => has$1(elem, 'data-mce-bogus') || ancestor$2(elem, '[data-mce-bogus="all"]', isRoot$1(root));
5445
    const findMarkers = (editor, uid) => {
5446
      const body = SugarElement.fromDom(editor.getBody());
5447
      const descendants$1 = descendants(body, `[${ dataAnnotationId() }="${ uid }"]`);
5448
      return filter$5(descendants$1, descendant => !isBogusElement(descendant, body));
5449
    };
5450
    const findAll = (editor, name) => {
5451
      const body = SugarElement.fromDom(editor.getBody());
5452
      const markers = descendants(body, `[${ dataAnnotation() }="${ name }"]`);
5453
      const directory = {};
5454
      each$e(markers, m => {
5455
        if (!isBogusElement(m, body)) {
5456
          const uid = get$9(m, dataAnnotationId());
5457
          const nodesAlready = get$a(directory, uid).getOr([]);
5458
          directory[uid] = nodesAlready.concat([m]);
5459
        }
5460
      });
5461
      return directory;
5462
    };
5463
 
5464
    const setup$y = (editor, registry) => {
5465
      const changeCallbacks = Cell({});
5466
      const initData = () => ({
5467
        listeners: [],
5468
        previous: value$2()
5469
      });
5470
      const withCallbacks = (name, f) => {
5471
        updateCallbacks(name, data => {
5472
          f(data);
5473
          return data;
5474
        });
5475
      };
5476
      const updateCallbacks = (name, f) => {
5477
        const callbackMap = changeCallbacks.get();
5478
        const data = get$a(callbackMap, name).getOrThunk(initData);
5479
        const outputData = f(data);
5480
        callbackMap[name] = outputData;
5481
        changeCallbacks.set(callbackMap);
5482
      };
5483
      const fireCallbacks = (name, uid, elements) => {
5484
        withCallbacks(name, data => {
5485
          each$e(data.listeners, f => f(true, name, {
5486
            uid,
5487
            nodes: map$3(elements, elem => elem.dom)
5488
          }));
5489
        });
5490
      };
5491
      const fireNoAnnotation = name => {
5492
        withCallbacks(name, data => {
5493
          each$e(data.listeners, f => f(false, name));
5494
        });
5495
      };
5496
      const toggleActiveAttr = (uid, state) => {
5497
        each$e(findMarkers(editor, uid), elem => {
5498
          if (state) {
5499
            set$3(elem, dataAnnotationActive(), 'true');
5500
          } else {
5501
            remove$a(elem, dataAnnotationActive());
5502
          }
5503
        });
5504
      };
5505
      const onNodeChange = last$1(() => {
5506
        const annotations = sort(registry.getNames());
5507
        each$e(annotations, name => {
5508
          updateCallbacks(name, data => {
5509
            const prev = data.previous.get();
5510
            identify(editor, Optional.some(name)).fold(() => {
5511
              prev.each(uid => {
5512
                fireNoAnnotation(name);
5513
                data.previous.clear();
5514
                toggleActiveAttr(uid, false);
5515
              });
5516
            }, ({uid, name, elements}) => {
5517
              if (!is$2(prev, uid)) {
5518
                prev.each(uid => toggleActiveAttr(uid, false));
5519
                fireCallbacks(name, uid, elements);
5520
                data.previous.set(uid);
5521
                toggleActiveAttr(uid, true);
5522
              }
5523
            });
5524
            return {
5525
              previous: data.previous,
5526
              listeners: data.listeners
5527
            };
5528
          });
5529
        });
5530
      }, 30);
5531
      editor.on('remove', () => {
5532
        onNodeChange.cancel();
5533
      });
5534
      editor.on('NodeChange', () => {
5535
        onNodeChange.throttle();
5536
      });
5537
      const addListener = (name, f) => {
5538
        updateCallbacks(name, data => ({
5539
          previous: data.previous,
5540
          listeners: data.listeners.concat([f])
5541
        }));
5542
      };
5543
      return { addListener };
5544
    };
5545
 
5546
    const setup$x = (editor, registry) => {
5547
      const dataAnnotation$1 = dataAnnotation();
5548
      const identifyParserNode = node => Optional.from(node.attr(dataAnnotation$1)).bind(registry.lookup);
5549
      const removeDirectAnnotation = node => {
5550
        var _a, _b;
5551
        node.attr(dataAnnotationId(), null);
5552
        node.attr(dataAnnotation(), null);
5553
        node.attr(dataAnnotationActive(), null);
5554
        const customAttrNames = Optional.from(node.attr(dataAnnotationAttributes())).map(names => names.split(',')).getOr([]);
5555
        const customClasses = Optional.from(node.attr(dataAnnotationClasses())).map(names => names.split(',')).getOr([]);
5556
        each$e(customAttrNames, name => node.attr(name, null));
5557
        const classList = (_b = (_a = node.attr('class')) === null || _a === void 0 ? void 0 : _a.split(' ')) !== null && _b !== void 0 ? _b : [];
5558
        const newClassList = difference(classList, [annotation()].concat(customClasses));
5559
        node.attr('class', newClassList.length > 0 ? newClassList.join(' ') : null);
5560
        node.attr(dataAnnotationClasses(), null);
5561
        node.attr(dataAnnotationAttributes(), null);
5562
      };
5563
      editor.serializer.addTempAttr(dataAnnotationActive());
5564
      editor.serializer.addAttributeFilter(dataAnnotation$1, nodes => {
5565
        for (const node of nodes) {
5566
          identifyParserNode(node).each(settings => {
5567
            if (settings.persistent === false) {
5568
              if (node.name === 'span') {
5569
                node.unwrap();
5570
              } else {
5571
                removeDirectAnnotation(node);
5572
              }
5573
            }
5574
          });
5575
        }
5576
      });
5577
    };
5578
 
5579
    const create$c = () => {
5580
      const annotations = {};
5581
      const register = (name, settings) => {
5582
        annotations[name] = {
5583
          name,
5584
          settings
5585
        };
5586
      };
5587
      const lookup = name => get$a(annotations, name).map(a => a.settings);
5588
      const getNames = () => keys(annotations);
5589
      return {
5590
        register,
5591
        lookup,
5592
        getNames
5593
      };
5594
    };
5595
 
5596
    let unique = 0;
5597
    const generate$1 = prefix => {
5598
      const date = new Date();
5599
      const time = date.getTime();
5600
      const random = Math.floor(Math.random() * 1000000000);
5601
      unique++;
5602
      return prefix + '_' + random + unique + String(time);
5603
    };
5604
 
5605
    const add = (element, classes) => {
5606
      each$e(classes, x => {
5607
        add$2(element, x);
5608
      });
5609
    };
5610
    const remove$4 = (element, classes) => {
5611
      each$e(classes, x => {
5612
        remove$7(element, x);
5613
      });
5614
    };
5615
 
5616
    const clone$2 = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
5617
    const shallow$1 = original => clone$2(original, false);
5618
    const deep$1 = original => clone$2(original, true);
5619
    const shallowAs = (original, tag) => {
5620
      const nu = SugarElement.fromTag(tag);
5621
      const attributes = clone$4(original);
5622
      setAll$1(nu, attributes);
5623
      return nu;
5624
    };
5625
    const mutate = (original, tag) => {
5626
      const nu = shallowAs(original, tag);
5627
      after$4(original, nu);
5628
      const children = children$1(original);
5629
      append(nu, children);
5630
      remove$5(original);
5631
      return nu;
5632
    };
5633
 
5634
    const TextWalker = (startNode, rootNode, isBoundary = never) => {
5635
      const walker = new DomTreeWalker(startNode, rootNode);
5636
      const walk = direction => {
5637
        let next;
5638
        do {
5639
          next = walker[direction]();
5640
        } while (next && !isText$a(next) && !isBoundary(next));
5641
        return Optional.from(next).filter(isText$a);
5642
      };
5643
      return {
5644
        current: () => Optional.from(walker.current()).filter(isText$a),
5645
        next: () => walk('next'),
5646
        prev: () => walk('prev'),
5647
        prev2: () => walk('prev2')
5648
      };
5649
    };
5650
 
5651
    const TextSeeker = (dom, isBoundary) => {
5652
      const isBlockBoundary = isBoundary ? isBoundary : node => dom.isBlock(node) || isBr$6(node) || isContentEditableFalse$b(node);
5653
      const walk = (node, offset, walker, process) => {
5654
        if (isText$a(node)) {
5655
          const newOffset = process(node, offset, node.data);
5656
          if (newOffset !== -1) {
5657
            return Optional.some({
5658
              container: node,
5659
              offset: newOffset
5660
            });
5661
          }
5662
        }
5663
        return walker().bind(next => walk(next.container, next.offset, walker, process));
5664
      };
5665
      const backwards = (node, offset, process, root) => {
5666
        const walker = TextWalker(node, root !== null && root !== void 0 ? root : dom.getRoot(), isBlockBoundary);
5667
        return walk(node, offset, () => walker.prev().map(prev => ({
5668
          container: prev,
5669
          offset: prev.length
5670
        })), process).getOrNull();
5671
      };
5672
      const forwards = (node, offset, process, root) => {
5673
        const walker = TextWalker(node, root !== null && root !== void 0 ? root : dom.getRoot(), isBlockBoundary);
5674
        return walk(node, offset, () => walker.next().map(next => ({
5675
          container: next,
5676
          offset: 0
5677
        })), process).getOrNull();
5678
      };
5679
      return {
5680
        backwards,
5681
        forwards
5682
      };
5683
    };
5684
 
5685
    const round$2 = Math.round;
5686
    const clone$1 = rect => {
5687
      if (!rect) {
5688
        return {
5689
          left: 0,
5690
          top: 0,
5691
          bottom: 0,
5692
          right: 0,
5693
          width: 0,
5694
          height: 0
5695
        };
5696
      }
5697
      return {
5698
        left: round$2(rect.left),
5699
        top: round$2(rect.top),
5700
        bottom: round$2(rect.bottom),
5701
        right: round$2(rect.right),
5702
        width: round$2(rect.width),
5703
        height: round$2(rect.height)
5704
      };
5705
    };
5706
    const collapse = (rect, toStart) => {
5707
      rect = clone$1(rect);
5708
      if (toStart) {
5709
        rect.right = rect.left;
5710
      } else {
5711
        rect.left = rect.left + rect.width;
5712
        rect.right = rect.left;
5713
      }
5714
      rect.width = 0;
5715
      return rect;
5716
    };
5717
    const isEqual = (rect1, rect2) => rect1.left === rect2.left && rect1.top === rect2.top && rect1.bottom === rect2.bottom && rect1.right === rect2.right;
5718
    const isValidOverflow = (overflowY, rect1, rect2) => overflowY >= 0 && overflowY <= Math.min(rect1.height, rect2.height) / 2;
5719
    const isAbove$1 = (rect1, rect2) => {
5720
      const halfHeight = Math.min(rect2.height / 2, rect1.height / 2);
5721
      if (rect1.bottom - halfHeight < rect2.top) {
5722
        return true;
5723
      }
5724
      if (rect1.top > rect2.bottom) {
5725
        return false;
5726
      }
5727
      return isValidOverflow(rect2.top - rect1.bottom, rect1, rect2);
5728
    };
5729
    const isBelow$1 = (rect1, rect2) => {
5730
      if (rect1.top > rect2.bottom) {
5731
        return true;
5732
      }
5733
      if (rect1.bottom < rect2.top) {
5734
        return false;
5735
      }
5736
      return isValidOverflow(rect2.bottom - rect1.top, rect1, rect2);
5737
    };
5738
    const containsXY = (rect, clientX, clientY) => clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
5739
    const boundingClientRectFromRects = rects => {
5740
      return foldl(rects, (acc, rect) => {
5741
        return acc.fold(() => Optional.some(rect), prevRect => {
5742
          const left = Math.min(rect.left, prevRect.left);
5743
          const top = Math.min(rect.top, prevRect.top);
5744
          const right = Math.max(rect.right, prevRect.right);
5745
          const bottom = Math.max(rect.bottom, prevRect.bottom);
5746
          return Optional.some({
5747
            top,
5748
            right,
5749
            bottom,
5750
            left,
5751
            width: right - left,
5752
            height: bottom - top
5753
          });
5754
        });
5755
      }, Optional.none());
5756
    };
5757
    const distanceToRectEdgeFromXY = (rect, x, y) => {
5758
      const cx = Math.max(Math.min(x, rect.left + rect.width), rect.left);
5759
      const cy = Math.max(Math.min(y, rect.top + rect.height), rect.top);
5760
      return Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
5761
    };
5762
    const overlapY = (r1, r2) => Math.max(0, Math.min(r1.bottom, r2.bottom) - Math.max(r1.top, r2.top));
5763
 
5764
    const clamp$2 = (value, min, max) => Math.min(Math.max(value, min), max);
5765
 
5766
    const getSelectedNode = range => {
5767
      const startContainer = range.startContainer, startOffset = range.startOffset;
5768
      if (startContainer === range.endContainer && startContainer.hasChildNodes() && range.endOffset === startOffset + 1) {
5769
        return startContainer.childNodes[startOffset];
5770
      }
5771
      return null;
5772
    };
5773
    const getNode$1 = (container, offset) => {
5774
      if (isElement$6(container) && container.hasChildNodes()) {
5775
        const childNodes = container.childNodes;
5776
        const safeOffset = clamp$2(offset, 0, childNodes.length - 1);
5777
        return childNodes[safeOffset];
5778
      } else {
5779
        return container;
5780
      }
5781
    };
5782
    const getNodeUnsafe = (container, offset) => {
5783
      if (offset < 0 && isElement$6(container) && container.hasChildNodes()) {
5784
        return undefined;
5785
      } else {
5786
        return getNode$1(container, offset);
5787
      }
5788
    };
5789
 
5790
    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]');
5791
    const isExtendingChar = ch => isString(ch) && ch.charCodeAt(0) >= 768 && extendingChars.test(ch);
5792
 
5793
    const or = (...args) => {
5794
      return x => {
5795
        for (let i = 0; i < args.length; i++) {
5796
          if (args[i](x)) {
5797
            return true;
5798
          }
5799
        }
5800
        return false;
5801
      };
5802
    };
5803
    const and = (...args) => {
5804
      return x => {
5805
        for (let i = 0; i < args.length; i++) {
5806
          if (!args[i](x)) {
5807
            return false;
5808
          }
5809
        }
5810
        return true;
5811
      };
5812
    };
5813
 
5814
    const isElement$4 = isElement$6;
5815
    const isCaretCandidate$2 = isCaretCandidate$3;
5816
    const isBlock$2 = matchStyleValues('display', 'block table');
5817
    const isFloated = matchStyleValues('float', 'left right');
5818
    const isValidElementCaretCandidate = and(isElement$4, isCaretCandidate$2, not(isFloated));
5819
    const isNotPre = not(matchStyleValues('white-space', 'pre pre-line pre-wrap'));
5820
    const isText$7 = isText$a;
5821
    const isBr$3 = isBr$6;
5822
    const nodeIndex$1 = DOMUtils.nodeIndex;
5823
    const resolveIndex$1 = getNodeUnsafe;
5824
    const createRange$1 = doc => doc ? doc.createRange() : DOMUtils.DOM.createRng();
5825
    const isWhiteSpace$1 = chr => isString(chr) && /[\r\n\t ]/.test(chr);
5826
    const isRange = rng => !!rng.setStart && !!rng.setEnd;
5827
    const isHiddenWhiteSpaceRange = range => {
5828
      const container = range.startContainer;
5829
      const offset = range.startOffset;
5830
      if (isWhiteSpace$1(range.toString()) && isNotPre(container.parentNode) && isText$a(container)) {
5831
        const text = container.data;
5832
        if (isWhiteSpace$1(text[offset - 1]) || isWhiteSpace$1(text[offset + 1])) {
5833
          return true;
5834
        }
5835
      }
5836
      return false;
5837
    };
5838
    const getBrClientRect = brNode => {
5839
      const doc = brNode.ownerDocument;
5840
      const rng = createRange$1(doc);
5841
      const nbsp$1 = doc.createTextNode(nbsp);
5842
      const parentNode = brNode.parentNode;
5843
      parentNode.insertBefore(nbsp$1, brNode);
5844
      rng.setStart(nbsp$1, 0);
5845
      rng.setEnd(nbsp$1, 1);
5846
      const clientRect = clone$1(rng.getBoundingClientRect());
5847
      parentNode.removeChild(nbsp$1);
5848
      return clientRect;
5849
    };
5850
    const getBoundingClientRectWebKitText = rng => {
5851
      const sc = rng.startContainer;
5852
      const ec = rng.endContainer;
5853
      const so = rng.startOffset;
5854
      const eo = rng.endOffset;
5855
      if (sc === ec && isText$a(ec) && so === 0 && eo === 1) {
5856
        const newRng = rng.cloneRange();
5857
        newRng.setEndAfter(ec);
5858
        return getBoundingClientRect$1(newRng);
5859
      } else {
5860
        return null;
5861
      }
5862
    };
5863
    const isZeroRect = r => r.left === 0 && r.right === 0 && r.top === 0 && r.bottom === 0;
5864
    const getBoundingClientRect$1 = item => {
5865
      var _a;
5866
      let clientRect;
5867
      const clientRects = item.getClientRects();
5868
      if (clientRects.length > 0) {
5869
        clientRect = clone$1(clientRects[0]);
5870
      } else {
5871
        clientRect = clone$1(item.getBoundingClientRect());
5872
      }
5873
      if (!isRange(item) && isBr$3(item) && isZeroRect(clientRect)) {
5874
        return getBrClientRect(item);
5875
      }
5876
      if (isZeroRect(clientRect) && isRange(item)) {
5877
        return (_a = getBoundingClientRectWebKitText(item)) !== null && _a !== void 0 ? _a : clientRect;
5878
      }
5879
      return clientRect;
5880
    };
5881
    const collapseAndInflateWidth = (clientRect, toStart) => {
5882
      const newClientRect = collapse(clientRect, toStart);
5883
      newClientRect.width = 1;
5884
      newClientRect.right = newClientRect.left + 1;
5885
      return newClientRect;
5886
    };
5887
    const getCaretPositionClientRects = caretPosition => {
5888
      const clientRects = [];
5889
      const addUniqueAndValidRect = clientRect => {
5890
        if (clientRect.height === 0) {
5891
          return;
5892
        }
5893
        if (clientRects.length > 0) {
5894
          if (isEqual(clientRect, clientRects[clientRects.length - 1])) {
5895
            return;
5896
          }
5897
        }
5898
        clientRects.push(clientRect);
5899
      };
5900
      const addCharacterOffset = (container, offset) => {
5901
        const range = createRange$1(container.ownerDocument);
5902
        if (offset < container.data.length) {
5903
          if (isExtendingChar(container.data[offset])) {
5904
            return;
5905
          }
5906
          if (isExtendingChar(container.data[offset - 1])) {
5907
            range.setStart(container, offset);
5908
            range.setEnd(container, offset + 1);
5909
            if (!isHiddenWhiteSpaceRange(range)) {
5910
              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), false));
5911
              return;
5912
            }
5913
          }
5914
        }
5915
        if (offset > 0) {
5916
          range.setStart(container, offset - 1);
5917
          range.setEnd(container, offset);
5918
          if (!isHiddenWhiteSpaceRange(range)) {
5919
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), false));
5920
          }
5921
        }
5922
        if (offset < container.data.length) {
5923
          range.setStart(container, offset);
5924
          range.setEnd(container, offset + 1);
5925
          if (!isHiddenWhiteSpaceRange(range)) {
5926
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(range), true));
5927
          }
5928
        }
5929
      };
5930
      const container = caretPosition.container();
5931
      const offset = caretPosition.offset();
5932
      if (isText$7(container)) {
5933
        addCharacterOffset(container, offset);
5934
        return clientRects;
5935
      }
5936
      if (isElement$4(container)) {
5937
        if (caretPosition.isAtEnd()) {
5938
          const node = resolveIndex$1(container, offset);
5939
          if (isText$7(node)) {
5940
            addCharacterOffset(node, node.data.length);
5941
          }
5942
          if (isValidElementCaretCandidate(node) && !isBr$3(node)) {
5943
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), false));
5944
          }
5945
        } else {
5946
          const node = resolveIndex$1(container, offset);
5947
          if (isText$7(node)) {
5948
            addCharacterOffset(node, 0);
5949
          }
5950
          if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) {
5951
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), false));
5952
            return clientRects;
5953
          }
5954
          const beforeNode = resolveIndex$1(caretPosition.container(), caretPosition.offset() - 1);
5955
          if (isValidElementCaretCandidate(beforeNode) && !isBr$3(beforeNode)) {
5956
            if (isBlock$2(beforeNode) || isBlock$2(node) || !isValidElementCaretCandidate(node)) {
5957
              addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(beforeNode), false));
5958
            }
5959
          }
5960
          if (isValidElementCaretCandidate(node)) {
5961
            addUniqueAndValidRect(collapseAndInflateWidth(getBoundingClientRect$1(node), true));
5962
          }
5963
        }
5964
      }
5965
      return clientRects;
5966
    };
5967
    const CaretPosition = (container, offset, clientRects) => {
5968
      const isAtStart = () => {
5969
        if (isText$7(container)) {
5970
          return offset === 0;
5971
        }
5972
        return offset === 0;
5973
      };
5974
      const isAtEnd = () => {
5975
        if (isText$7(container)) {
5976
          return offset >= container.data.length;
5977
        }
5978
        return offset >= container.childNodes.length;
5979
      };
5980
      const toRange = () => {
5981
        const range = createRange$1(container.ownerDocument);
5982
        range.setStart(container, offset);
5983
        range.setEnd(container, offset);
5984
        return range;
5985
      };
5986
      const getClientRects = () => {
5987
        if (!clientRects) {
5988
          clientRects = getCaretPositionClientRects(CaretPosition(container, offset));
5989
        }
5990
        return clientRects;
5991
      };
5992
      const isVisible = () => getClientRects().length > 0;
5993
      const isEqual = caretPosition => caretPosition && container === caretPosition.container() && offset === caretPosition.offset();
5994
      const getNode = before => resolveIndex$1(container, before ? offset - 1 : offset);
5995
      return {
5996
        container: constant(container),
5997
        offset: constant(offset),
5998
        toRange,
5999
        getClientRects,
6000
        isVisible,
6001
        isAtStart,
6002
        isAtEnd,
6003
        isEqual,
6004
        getNode
6005
      };
6006
    };
6007
    CaretPosition.fromRangeStart = range => CaretPosition(range.startContainer, range.startOffset);
6008
    CaretPosition.fromRangeEnd = range => CaretPosition(range.endContainer, range.endOffset);
6009
    CaretPosition.after = node => CaretPosition(node.parentNode, nodeIndex$1(node) + 1);
6010
    CaretPosition.before = node => CaretPosition(node.parentNode, nodeIndex$1(node));
6011
    CaretPosition.isAbove = (pos1, pos2) => lift2(head(pos2.getClientRects()), last$3(pos1.getClientRects()), isAbove$1).getOr(false);
6012
    CaretPosition.isBelow = (pos1, pos2) => lift2(last$3(pos2.getClientRects()), head(pos1.getClientRects()), isBelow$1).getOr(false);
6013
    CaretPosition.isAtStart = pos => pos ? pos.isAtStart() : false;
6014
    CaretPosition.isAtEnd = pos => pos ? pos.isAtEnd() : false;
6015
    CaretPosition.isTextPosition = pos => pos ? isText$a(pos.container()) : false;
6016
    CaretPosition.isElementPosition = pos => !CaretPosition.isTextPosition(pos);
6017
 
6018
    const trimEmptyTextNode$1 = (dom, node) => {
6019
      if (isText$a(node) && node.data.length === 0) {
6020
        dom.remove(node);
6021
      }
6022
    };
6023
    const insertNode = (dom, rng, node) => {
6024
      rng.insertNode(node);
6025
      trimEmptyTextNode$1(dom, node.previousSibling);
6026
      trimEmptyTextNode$1(dom, node.nextSibling);
6027
    };
6028
    const insertFragment = (dom, rng, frag) => {
6029
      const firstChild = Optional.from(frag.firstChild);
6030
      const lastChild = Optional.from(frag.lastChild);
6031
      rng.insertNode(frag);
6032
      firstChild.each(child => trimEmptyTextNode$1(dom, child.previousSibling));
6033
      lastChild.each(child => trimEmptyTextNode$1(dom, child.nextSibling));
6034
    };
6035
    const rangeInsertNode = (dom, rng, node) => {
6036
      if (isDocumentFragment(node)) {
6037
        insertFragment(dom, rng, node);
6038
      } else {
6039
        insertNode(dom, rng, node);
6040
      }
6041
    };
6042
 
6043
    const isText$6 = isText$a;
6044
    const isBogus = isBogus$2;
6045
    const nodeIndex = DOMUtils.nodeIndex;
6046
    const normalizedParent = node => {
6047
      const parentNode = node.parentNode;
6048
      if (isBogus(parentNode)) {
6049
        return normalizedParent(parentNode);
6050
      }
6051
      return parentNode;
6052
    };
6053
    const getChildNodes = node => {
6054
      if (!node) {
6055
        return [];
6056
      }
6057
      return reduce(node.childNodes, (result, node) => {
6058
        if (isBogus(node) && node.nodeName !== 'BR') {
6059
          result = result.concat(getChildNodes(node));
6060
        } else {
6061
          result.push(node);
6062
        }
6063
        return result;
6064
      }, []);
6065
    };
6066
    const normalizedTextOffset = (node, offset) => {
6067
      let tempNode = node;
6068
      while (tempNode = tempNode.previousSibling) {
6069
        if (!isText$6(tempNode)) {
6070
          break;
6071
        }
6072
        offset += tempNode.data.length;
6073
      }
6074
      return offset;
6075
    };
6076
    const equal = a => b => a === b;
6077
    const normalizedNodeIndex = node => {
6078
      let nodes, index;
6079
      nodes = getChildNodes(normalizedParent(node));
6080
      index = findIndex$1(nodes, equal(node), node);
6081
      nodes = nodes.slice(0, index + 1);
6082
      const numTextFragments = reduce(nodes, (result, node, i) => {
6083
        if (isText$6(node) && isText$6(nodes[i - 1])) {
6084
          result++;
6085
        }
6086
        return result;
6087
      }, 0);
6088
      nodes = filter$3(nodes, matchNodeNames([node.nodeName]));
6089
      index = findIndex$1(nodes, equal(node), node);
6090
      return index - numTextFragments;
6091
    };
6092
    const createPathItem = node => {
6093
      const name = isText$6(node) ? 'text()' : node.nodeName.toLowerCase();
6094
      return name + '[' + normalizedNodeIndex(node) + ']';
6095
    };
6096
    const parentsUntil$1 = (root, node, predicate) => {
6097
      const parents = [];
6098
      for (let tempNode = node.parentNode; tempNode && tempNode !== root; tempNode = tempNode.parentNode) {
6099
        if (predicate && predicate(tempNode)) {
6100
          break;
6101
        }
6102
        parents.push(tempNode);
6103
      }
6104
      return parents;
6105
    };
6106
    const create$b = (root, caretPosition) => {
6107
      let path = [];
6108
      let container = caretPosition.container();
6109
      let offset = caretPosition.offset();
6110
      let outputOffset;
6111
      if (isText$6(container)) {
6112
        outputOffset = normalizedTextOffset(container, offset);
6113
      } else {
6114
        const childNodes = container.childNodes;
6115
        if (offset >= childNodes.length) {
6116
          outputOffset = 'after';
6117
          offset = childNodes.length - 1;
6118
        } else {
6119
          outputOffset = 'before';
6120
        }
6121
        container = childNodes[offset];
6122
      }
6123
      path.push(createPathItem(container));
6124
      let parents = parentsUntil$1(root, container);
6125
      parents = filter$3(parents, not(isBogus$2));
6126
      path = path.concat(map$1(parents, node => {
6127
        return createPathItem(node);
6128
      }));
6129
      return path.reverse().join('/') + ',' + outputOffset;
6130
    };
6131
    const resolvePathItem = (node, name, index) => {
6132
      let nodes = getChildNodes(node);
6133
      nodes = filter$3(nodes, (node, index) => {
6134
        return !isText$6(node) || !isText$6(nodes[index - 1]);
6135
      });
6136
      nodes = filter$3(nodes, matchNodeNames([name]));
6137
      return nodes[index];
6138
    };
6139
    const findTextPosition = (container, offset) => {
6140
      let node = container;
6141
      let targetOffset = 0;
6142
      while (isText$6(node)) {
6143
        const dataLen = node.data.length;
6144
        if (offset >= targetOffset && offset <= targetOffset + dataLen) {
6145
          container = node;
6146
          offset = offset - targetOffset;
6147
          break;
6148
        }
6149
        if (!isText$6(node.nextSibling)) {
6150
          container = node;
6151
          offset = dataLen;
6152
          break;
6153
        }
6154
        targetOffset += dataLen;
6155
        node = node.nextSibling;
6156
      }
6157
      if (isText$6(container) && offset > container.data.length) {
6158
        offset = container.data.length;
6159
      }
6160
      return CaretPosition(container, offset);
6161
    };
6162
    const resolve$1 = (root, path) => {
6163
      if (!path) {
6164
        return null;
6165
      }
6166
      const parts = path.split(',');
6167
      const paths = parts[0].split('/');
6168
      const offset = parts.length > 1 ? parts[1] : 'before';
6169
      const container = reduce(paths, (result, value) => {
6170
        const match = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value);
6171
        if (!match) {
6172
          return null;
6173
        }
6174
        if (match[1] === 'text()') {
6175
          match[1] = '#text';
6176
        }
6177
        return resolvePathItem(result, match[1], parseInt(match[2], 10));
6178
      }, root);
6179
      if (!container) {
6180
        return null;
6181
      }
6182
      if (!isText$6(container) && container.parentNode) {
6183
        let nodeOffset;
6184
        if (offset === 'after') {
6185
          nodeOffset = nodeIndex(container) + 1;
6186
        } else {
6187
          nodeOffset = nodeIndex(container);
6188
        }
6189
        return CaretPosition(container.parentNode, nodeOffset);
6190
      }
6191
      return findTextPosition(container, parseInt(offset, 10));
6192
    };
6193
 
6194
    const isContentEditableFalse$9 = isContentEditableFalse$b;
6195
    const getNormalizedTextOffset$1 = (trim, container, offset) => {
6196
      let trimmedOffset = trim(container.data.slice(0, offset)).length;
6197
      for (let node = container.previousSibling; node && isText$a(node); node = node.previousSibling) {
6198
        trimmedOffset += trim(node.data).length;
6199
      }
6200
      return trimmedOffset;
6201
    };
6202
    const getPoint = (dom, trim, normalized, rng, start) => {
6203
      const container = start ? rng.startContainer : rng.endContainer;
6204
      let offset = start ? rng.startOffset : rng.endOffset;
6205
      const point = [];
6206
      const root = dom.getRoot();
6207
      if (isText$a(container)) {
6208
        point.push(normalized ? getNormalizedTextOffset$1(trim, container, offset) : offset);
6209
      } else {
6210
        let after = 0;
6211
        const childNodes = container.childNodes;
6212
        if (offset >= childNodes.length && childNodes.length) {
6213
          after = 1;
6214
          offset = Math.max(0, childNodes.length - 1);
6215
        }
6216
        point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
6217
      }
6218
      for (let node = container; node && node !== root; node = node.parentNode) {
6219
        point.push(dom.nodeIndex(node, normalized));
6220
      }
6221
      return point;
6222
    };
6223
    const getLocation = (trim, selection, normalized, rng) => {
6224
      const dom = selection.dom;
6225
      const start = getPoint(dom, trim, normalized, rng, true);
6226
      const forward = selection.isForward();
6227
      const fakeCaret = isRangeInCaretContainerBlock(rng) ? { isFakeCaret: true } : {};
6228
      if (!selection.isCollapsed()) {
6229
        const end = getPoint(dom, trim, normalized, rng, false);
6230
        return {
6231
          start,
6232
          end,
6233
          forward,
6234
          ...fakeCaret
6235
        };
6236
      } else {
6237
        return {
6238
          start,
6239
          forward,
6240
          ...fakeCaret
6241
        };
6242
      }
6243
    };
6244
    const findIndex = (dom, name, element) => {
6245
      let count = 0;
6246
      Tools.each(dom.select(name), node => {
6247
        if (node.getAttribute('data-mce-bogus') === 'all') {
6248
          return;
6249
        } else if (node === element) {
6250
          return false;
6251
        } else {
6252
          count++;
6253
          return;
6254
        }
6255
      });
6256
      return count;
6257
    };
6258
    const moveEndPoint$1 = (rng, start) => {
6259
      let container = start ? rng.startContainer : rng.endContainer;
6260
      let offset = start ? rng.startOffset : rng.endOffset;
6261
      if (isElement$6(container) && container.nodeName === 'TR') {
6262
        const childNodes = container.childNodes;
6263
        container = childNodes[Math.min(start ? offset : offset - 1, childNodes.length - 1)];
6264
        if (container) {
6265
          offset = start ? 0 : container.childNodes.length;
6266
          if (start) {
6267
            rng.setStart(container, offset);
6268
          } else {
6269
            rng.setEnd(container, offset);
6270
          }
6271
        }
6272
      }
6273
    };
6274
    const normalizeTableCellSelection = rng => {
6275
      moveEndPoint$1(rng, true);
6276
      moveEndPoint$1(rng, false);
6277
      return rng;
6278
    };
6279
    const findSibling = (node, offset) => {
6280
      if (isElement$6(node)) {
6281
        node = getNode$1(node, offset);
6282
        if (isContentEditableFalse$9(node)) {
6283
          return node;
6284
        }
6285
      }
6286
      if (isCaretContainer$2(node)) {
6287
        if (isText$a(node) && isCaretContainerBlock$1(node)) {
6288
          node = node.parentNode;
6289
        }
6290
        let sibling = node.previousSibling;
6291
        if (isContentEditableFalse$9(sibling)) {
6292
          return sibling;
6293
        }
6294
        sibling = node.nextSibling;
6295
        if (isContentEditableFalse$9(sibling)) {
6296
          return sibling;
6297
        }
6298
      }
6299
      return undefined;
6300
    };
6301
    const findAdjacentContentEditableFalseElm = rng => {
6302
      return findSibling(rng.startContainer, rng.startOffset) || findSibling(rng.endContainer, rng.endOffset);
6303
    };
6304
    const getOffsetBookmark = (trim, normalized, selection) => {
6305
      const element = selection.getNode();
6306
      const rng = selection.getRng();
6307
      if (element.nodeName === 'IMG' || isContentEditableFalse$9(element)) {
6308
        const name = element.nodeName;
6309
        return {
6310
          name,
6311
          index: findIndex(selection.dom, name, element)
6312
        };
6313
      }
6314
      const sibling = findAdjacentContentEditableFalseElm(rng);
6315
      if (sibling) {
6316
        const name = sibling.tagName;
6317
        return {
6318
          name,
6319
          index: findIndex(selection.dom, name, sibling)
6320
        };
6321
      }
6322
      return getLocation(trim, selection, normalized, rng);
6323
    };
6324
    const getCaretBookmark = selection => {
6325
      const rng = selection.getRng();
6326
      return {
6327
        start: create$b(selection.dom.getRoot(), CaretPosition.fromRangeStart(rng)),
6328
        end: create$b(selection.dom.getRoot(), CaretPosition.fromRangeEnd(rng)),
6329
        forward: selection.isForward()
6330
      };
6331
    };
6332
    const getRangeBookmark = selection => {
6333
      return {
6334
        rng: selection.getRng(),
6335
        forward: selection.isForward()
6336
      };
6337
    };
6338
    const createBookmarkSpan = (dom, id, filled) => {
6339
      const args = {
6340
        'data-mce-type': 'bookmark',
6341
        id,
6342
        'style': 'overflow:hidden;line-height:0px'
6343
      };
6344
      return filled ? dom.create('span', args, '&#xFEFF;') : dom.create('span', args);
6345
    };
6346
    const getPersistentBookmark = (selection, filled) => {
6347
      const dom = selection.dom;
6348
      let rng = selection.getRng();
6349
      const id = dom.uniqueId();
6350
      const collapsed = selection.isCollapsed();
6351
      const element = selection.getNode();
6352
      const name = element.nodeName;
6353
      const forward = selection.isForward();
6354
      if (name === 'IMG') {
6355
        return {
6356
          name,
6357
          index: findIndex(dom, name, element)
6358
        };
6359
      }
6360
      const rng2 = normalizeTableCellSelection(rng.cloneRange());
6361
      if (!collapsed) {
6362
        rng2.collapse(false);
6363
        const endBookmarkNode = createBookmarkSpan(dom, id + '_end', filled);
6364
        rangeInsertNode(dom, rng2, endBookmarkNode);
6365
      }
6366
      rng = normalizeTableCellSelection(rng);
6367
      rng.collapse(true);
6368
      const startBookmarkNode = createBookmarkSpan(dom, id + '_start', filled);
6369
      rangeInsertNode(dom, rng, startBookmarkNode);
6370
      selection.moveToBookmark({
6371
        id,
6372
        keep: true,
6373
        forward
6374
      });
6375
      return {
6376
        id,
6377
        forward
6378
      };
6379
    };
6380
    const getBookmark$2 = (selection, type, normalized = false) => {
6381
      if (type === 2) {
6382
        return getOffsetBookmark(trim$2, normalized, selection);
6383
      } else if (type === 3) {
6384
        return getCaretBookmark(selection);
6385
      } else if (type) {
6386
        return getRangeBookmark(selection);
6387
      } else {
6388
        return getPersistentBookmark(selection, false);
6389
      }
6390
    };
6391
    const getUndoBookmark = curry(getOffsetBookmark, identity, true);
6392
 
6393
    const value$1 = value => {
6394
      const applyHelper = fn => fn(value);
6395
      const constHelper = constant(value);
6396
      const outputHelper = () => output;
6397
      const output = {
6398
        tag: true,
6399
        inner: value,
6400
        fold: (_onError, onValue) => onValue(value),
6401
        isValue: always,
6402
        isError: never,
6403
        map: mapper => Result.value(mapper(value)),
6404
        mapError: outputHelper,
6405
        bind: applyHelper,
6406
        exists: applyHelper,
6407
        forall: applyHelper,
6408
        getOr: constHelper,
6409
        or: outputHelper,
6410
        getOrThunk: constHelper,
6411
        orThunk: outputHelper,
6412
        getOrDie: constHelper,
6413
        each: fn => {
6414
          fn(value);
6415
        },
6416
        toOptional: () => Optional.some(value)
6417
      };
6418
      return output;
6419
    };
6420
    const error = error => {
6421
      const outputHelper = () => output;
6422
      const output = {
6423
        tag: false,
6424
        inner: error,
6425
        fold: (onError, _onValue) => onError(error),
6426
        isValue: never,
6427
        isError: always,
6428
        map: outputHelper,
6429
        mapError: mapper => Result.error(mapper(error)),
6430
        bind: outputHelper,
6431
        exists: never,
6432
        forall: always,
6433
        getOr: identity,
6434
        or: identity,
6435
        getOrThunk: apply$1,
6436
        orThunk: apply$1,
6437
        getOrDie: die(String(error)),
6438
        each: noop,
6439
        toOptional: Optional.none
6440
      };
6441
      return output;
6442
    };
6443
    const fromOption = (optional, err) => optional.fold(() => error(err), value$1);
6444
    const Result = {
6445
      value: value$1,
6446
      error,
6447
      fromOption
6448
    };
6449
 
6450
    const generate = cases => {
6451
      if (!isArray$1(cases)) {
6452
        throw new Error('cases must be an array');
6453
      }
6454
      if (cases.length === 0) {
6455
        throw new Error('there must be at least one case');
6456
      }
6457
      const constructors = [];
6458
      const adt = {};
6459
      each$e(cases, (acase, count) => {
6460
        const keys$1 = keys(acase);
6461
        if (keys$1.length !== 1) {
6462
          throw new Error('one and only one name per case');
6463
        }
6464
        const key = keys$1[0];
6465
        const value = acase[key];
6466
        if (adt[key] !== undefined) {
6467
          throw new Error('duplicate key detected:' + key);
6468
        } else if (key === 'cata') {
6469
          throw new Error('cannot have a case named cata (sorry)');
6470
        } else if (!isArray$1(value)) {
6471
          throw new Error('case arguments must be an array');
6472
        }
6473
        constructors.push(key);
6474
        adt[key] = (...args) => {
6475
          const argLength = args.length;
6476
          if (argLength !== value.length) {
6477
            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
6478
          }
6479
          const match = branches => {
6480
            const branchKeys = keys(branches);
6481
            if (constructors.length !== branchKeys.length) {
6482
              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
6483
            }
6484
            const allReqd = forall(constructors, reqKey => {
6485
              return contains$2(branchKeys, reqKey);
6486
            });
6487
            if (!allReqd) {
6488
              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
6489
            }
6490
            return branches[key].apply(null, args);
6491
          };
6492
          return {
6493
            fold: (...foldArgs) => {
6494
              if (foldArgs.length !== cases.length) {
6495
                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
6496
              }
6497
              const target = foldArgs[count];
6498
              return target.apply(null, args);
6499
            },
6500
            match,
6501
            log: label => {
6502
              console.log(label, {
6503
                constructors,
6504
                constructor: key,
6505
                params: args
6506
              });
6507
            }
6508
          };
6509
        };
6510
      });
6511
      return adt;
6512
    };
6513
    const Adt = { generate };
6514
 
6515
    Adt.generate([
6516
      {
6517
        bothErrors: [
6518
          'error1',
6519
          'error2'
6520
        ]
6521
      },
6522
      {
6523
        firstError: [
6524
          'error1',
6525
          'value2'
6526
        ]
6527
      },
6528
      {
6529
        secondError: [
6530
          'value1',
6531
          'error2'
6532
        ]
6533
      },
6534
      {
6535
        bothValues: [
6536
          'value1',
6537
          'value2'
6538
        ]
6539
      }
6540
    ]);
6541
    const partition$1 = results => {
6542
      const errors = [];
6543
      const values = [];
6544
      each$e(results, result => {
6545
        result.fold(err => {
6546
          errors.push(err);
6547
        }, value => {
6548
          values.push(value);
6549
        });
6550
      });
6551
      return {
6552
        errors,
6553
        values
6554
      };
6555
    };
6556
 
6557
    const isInlinePattern = pattern => pattern.type === 'inline-command' || pattern.type === 'inline-format';
6558
    const isBlockPattern = pattern => pattern.type === 'block-command' || pattern.type === 'block-format';
6559
    const normalizePattern = pattern => {
6560
      const err = message => Result.error({
6561
        message,
6562
        pattern
6563
      });
6564
      const formatOrCmd = (name, onFormat, onCommand) => {
6565
        if (pattern.format !== undefined) {
6566
          let formats;
6567
          if (isArray$1(pattern.format)) {
6568
            if (!forall(pattern.format, isString)) {
6569
              return err(name + ' pattern has non-string items in the `format` array');
6570
            }
6571
            formats = pattern.format;
6572
          } else if (isString(pattern.format)) {
6573
            formats = [pattern.format];
6574
          } else {
6575
            return err(name + ' pattern has non-string `format` parameter');
6576
          }
6577
          return Result.value(onFormat(formats));
6578
        } else if (pattern.cmd !== undefined) {
6579
          if (!isString(pattern.cmd)) {
6580
            return err(name + ' pattern has non-string `cmd` parameter');
6581
          }
6582
          return Result.value(onCommand(pattern.cmd, pattern.value));
6583
        } else {
6584
          return err(name + ' pattern is missing both `format` and `cmd` parameters');
6585
        }
6586
      };
6587
      if (!isObject(pattern)) {
6588
        return err('Raw pattern is not an object');
6589
      }
6590
      if (!isString(pattern.start)) {
6591
        return err('Raw pattern is missing `start` parameter');
6592
      }
6593
      if (pattern.end !== undefined) {
6594
        if (!isString(pattern.end)) {
6595
          return err('Inline pattern has non-string `end` parameter');
6596
        }
6597
        if (pattern.start.length === 0 && pattern.end.length === 0) {
6598
          return err('Inline pattern has empty `start` and `end` parameters');
6599
        }
6600
        let start = pattern.start;
6601
        let end = pattern.end;
6602
        if (end.length === 0) {
6603
          end = start;
6604
          start = '';
6605
        }
6606
        return formatOrCmd('Inline', format => ({
6607
          type: 'inline-format',
6608
          start,
6609
          end,
6610
          format
6611
        }), (cmd, value) => ({
6612
          type: 'inline-command',
6613
          start,
6614
          end,
6615
          cmd,
6616
          value
6617
        }));
6618
      } else if (pattern.replacement !== undefined) {
6619
        if (!isString(pattern.replacement)) {
6620
          return err('Replacement pattern has non-string `replacement` parameter');
6621
        }
6622
        if (pattern.start.length === 0) {
6623
          return err('Replacement pattern has empty `start` parameter');
6624
        }
6625
        return Result.value({
6626
          type: 'inline-command',
6627
          start: '',
6628
          end: pattern.start,
6629
          cmd: 'mceInsertContent',
6630
          value: pattern.replacement
6631
        });
6632
      } else {
6633
        if (pattern.start.length === 0) {
6634
          return err('Block pattern has empty `start` parameter');
6635
        }
6636
        return formatOrCmd('Block', formats => ({
6637
          type: 'block-format',
6638
          start: pattern.start,
6639
          format: formats[0]
6640
        }), (command, commandValue) => ({
6641
          type: 'block-command',
6642
          start: pattern.start,
6643
          cmd: command,
6644
          value: commandValue
6645
        }));
6646
      }
6647
    };
6648
    const getBlockPatterns = patterns => filter$5(patterns, isBlockPattern);
6649
    const getInlinePatterns = patterns => filter$5(patterns, isInlinePattern);
6650
    const createPatternSet = (patterns, dynamicPatternsLookup) => ({
6651
      inlinePatterns: getInlinePatterns(patterns),
6652
      blockPatterns: getBlockPatterns(patterns),
6653
      dynamicPatternsLookup
6654
    });
6655
    const fromRawPatterns = patterns => {
6656
      const normalized = partition$1(map$3(patterns, normalizePattern));
6657
      each$e(normalized.errors, err => console.error(err.message, err.pattern));
6658
      return normalized.values;
6659
    };
6660
    const fromRawPatternsLookup = lookupFn => {
6661
      return ctx => {
6662
        const rawPatterns = lookupFn(ctx);
6663
        return fromRawPatterns(rawPatterns);
6664
      };
6665
    };
6666
 
6667
    const deviceDetection$1 = detect$2().deviceType;
6668
    const isTouch = deviceDetection$1.isTouch();
6669
    const DOM$a = DOMUtils.DOM;
6670
    const getHash = value => {
6671
      const items = value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(',');
6672
      return foldl(items, (output, item) => {
6673
        const arr = item.split('=');
6674
        const key = arr[0];
6675
        const val = arr.length > 1 ? arr[1] : key;
6676
        output[trim$4(key)] = trim$4(val);
6677
        return output;
6678
      }, {});
6679
    };
6680
    const isRegExp = x => is$4(x, RegExp);
6681
    const option = name => editor => editor.options.get(name);
6682
    const stringOrObjectProcessor = value => isString(value) || isObject(value);
6683
    const bodyOptionProcessor = (editor, defaultValue = '') => value => {
6684
      const valid = isString(value);
6685
      if (valid) {
6686
        if (value.indexOf('=') !== -1) {
6687
          const bodyObj = getHash(value);
6688
          return {
6689
            value: get$a(bodyObj, editor.id).getOr(defaultValue),
6690
            valid
6691
          };
6692
        } else {
6693
          return {
6694
            value,
6695
            valid
6696
          };
6697
        }
6698
      } else {
6699
        return {
6700
          valid: false,
6701
          message: 'Must be a string.'
6702
        };
6703
      }
6704
    };
6705
    const register$7 = editor => {
6706
      const registerOption = editor.options.register;
6707
      registerOption('id', {
6708
        processor: 'string',
6709
        default: editor.id
6710
      });
6711
      registerOption('selector', { processor: 'string' });
6712
      registerOption('target', { processor: 'object' });
6713
      registerOption('suffix', { processor: 'string' });
6714
      registerOption('cache_suffix', { processor: 'string' });
6715
      registerOption('base_url', { processor: 'string' });
6716
      registerOption('referrer_policy', {
6717
        processor: 'string',
6718
        default: ''
6719
      });
6720
      registerOption('language_load', {
6721
        processor: 'boolean',
6722
        default: true
6723
      });
6724
      registerOption('inline', {
6725
        processor: 'boolean',
6726
        default: false
6727
      });
6728
      registerOption('iframe_attrs', {
6729
        processor: 'object',
6730
        default: {}
6731
      });
6732
      registerOption('doctype', {
6733
        processor: 'string',
6734
        default: '<!DOCTYPE html>'
6735
      });
6736
      registerOption('document_base_url', {
6737
        processor: 'string',
6738
        default: editor.documentBaseUrl
6739
      });
6740
      registerOption('body_id', {
6741
        processor: bodyOptionProcessor(editor, 'tinymce'),
6742
        default: 'tinymce'
6743
      });
6744
      registerOption('body_class', {
6745
        processor: bodyOptionProcessor(editor),
6746
        default: ''
6747
      });
6748
      registerOption('content_security_policy', {
6749
        processor: 'string',
6750
        default: ''
6751
      });
6752
      registerOption('br_in_pre', {
6753
        processor: 'boolean',
6754
        default: true
6755
      });
6756
      registerOption('forced_root_block', {
6757
        processor: value => {
6758
          const valid = isString(value) && isNotEmpty(value);
6759
          if (valid) {
6760
            return {
6761
              value,
6762
              valid
6763
            };
6764
          } else {
6765
            return {
6766
              valid: false,
6767
              message: 'Must be a non-empty string.'
6768
            };
6769
          }
6770
        },
6771
        default: 'p'
6772
      });
6773
      registerOption('forced_root_block_attrs', {
6774
        processor: 'object',
6775
        default: {}
6776
      });
6777
      registerOption('newline_behavior', {
6778
        processor: value => {
6779
          const valid = contains$2([
6780
            'block',
6781
            'linebreak',
6782
            'invert',
6783
            'default'
6784
          ], value);
6785
          return valid ? {
6786
            value,
6787
            valid
6788
          } : {
6789
            valid: false,
6790
            message: 'Must be one of: block, linebreak, invert or default.'
6791
          };
6792
        },
6793
        default: 'default'
6794
      });
6795
      registerOption('br_newline_selector', {
6796
        processor: 'string',
6797
        default: '.mce-toc h2,figcaption,caption'
6798
      });
6799
      registerOption('no_newline_selector', {
6800
        processor: 'string',
6801
        default: ''
6802
      });
6803
      registerOption('keep_styles', {
6804
        processor: 'boolean',
6805
        default: true
6806
      });
6807
      registerOption('end_container_on_empty_block', {
6808
        processor: value => {
6809
          if (isBoolean(value)) {
6810
            return {
6811
              valid: true,
6812
              value
6813
            };
6814
          } else if (isString(value)) {
6815
            return {
6816
              valid: true,
6817
              value
6818
            };
6819
          } else {
6820
            return {
6821
              valid: false,
6822
              message: 'Must be boolean or a string'
6823
            };
6824
          }
6825
        },
6826
        default: 'blockquote'
6827
      });
6828
      registerOption('font_size_style_values', {
6829
        processor: 'string',
6830
        default: 'xx-small,x-small,small,medium,large,x-large,xx-large'
6831
      });
6832
      registerOption('font_size_legacy_values', {
6833
        processor: 'string',
6834
        default: 'xx-small,small,medium,large,x-large,xx-large,300%'
6835
      });
6836
      registerOption('font_size_classes', {
6837
        processor: 'string',
6838
        default: ''
6839
      });
6840
      registerOption('automatic_uploads', {
6841
        processor: 'boolean',
6842
        default: true
6843
      });
6844
      registerOption('images_reuse_filename', {
6845
        processor: 'boolean',
6846
        default: false
6847
      });
6848
      registerOption('images_replace_blob_uris', {
6849
        processor: 'boolean',
6850
        default: true
6851
      });
6852
      registerOption('icons', {
6853
        processor: 'string',
6854
        default: ''
6855
      });
6856
      registerOption('icons_url', {
6857
        processor: 'string',
6858
        default: ''
6859
      });
6860
      registerOption('images_upload_url', {
6861
        processor: 'string',
6862
        default: ''
6863
      });
6864
      registerOption('images_upload_base_path', {
6865
        processor: 'string',
6866
        default: ''
6867
      });
6868
      registerOption('images_upload_credentials', {
6869
        processor: 'boolean',
6870
        default: false
6871
      });
6872
      registerOption('images_upload_handler', { processor: 'function' });
6873
      registerOption('language', {
6874
        processor: 'string',
6875
        default: 'en'
6876
      });
6877
      registerOption('language_url', {
6878
        processor: 'string',
6879
        default: ''
6880
      });
6881
      registerOption('entity_encoding', {
6882
        processor: 'string',
6883
        default: 'named'
6884
      });
6885
      registerOption('indent', {
6886
        processor: 'boolean',
6887
        default: true
6888
      });
6889
      registerOption('indent_before', {
6890
        processor: 'string',
6891
        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'
6892
      });
6893
      registerOption('indent_after', {
6894
        processor: 'string',
6895
        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'
6896
      });
6897
      registerOption('indent_use_margin', {
6898
        processor: 'boolean',
6899
        default: false
6900
      });
6901
      registerOption('indentation', {
6902
        processor: 'string',
6903
        default: '40px'
6904
      });
6905
      registerOption('content_css', {
6906
        processor: value => {
6907
          const valid = value === false || isString(value) || isArrayOf(value, isString);
6908
          if (valid) {
6909
            if (isString(value)) {
6910
              return {
6911
                value: map$3(value.split(','), trim$4),
6912
                valid
6913
              };
6914
            } else if (isArray$1(value)) {
6915
              return {
6916
                value,
6917
                valid
6918
              };
6919
            } else if (value === false) {
6920
              return {
6921
                value: [],
6922
                valid
6923
              };
6924
            } else {
6925
              return {
6926
                value,
6927
                valid
6928
              };
6929
            }
6930
          } else {
6931
            return {
6932
              valid: false,
6933
              message: 'Must be false, a string or an array of strings.'
6934
            };
6935
          }
6936
        },
6937
        default: isInline$1(editor) ? [] : ['default']
6938
      });
6939
      registerOption('content_style', { processor: 'string' });
6940
      registerOption('content_css_cors', {
6941
        processor: 'boolean',
6942
        default: false
6943
      });
6944
      registerOption('font_css', {
6945
        processor: value => {
6946
          const valid = isString(value) || isArrayOf(value, isString);
6947
          if (valid) {
6948
            const newValue = isArray$1(value) ? value : map$3(value.split(','), trim$4);
6949
            return {
6950
              value: newValue,
6951
              valid
6952
            };
6953
          } else {
6954
            return {
6955
              valid: false,
6956
              message: 'Must be a string or an array of strings.'
6957
            };
6958
          }
6959
        },
6960
        default: []
6961
      });
6962
      registerOption('inline_boundaries', {
6963
        processor: 'boolean',
6964
        default: true
6965
      });
6966
      registerOption('inline_boundaries_selector', {
6967
        processor: 'string',
6968
        default: 'a[href],code,span.mce-annotation'
6969
      });
6970
      registerOption('object_resizing', {
6971
        processor: value => {
6972
          const valid = isBoolean(value) || isString(value);
6973
          if (valid) {
6974
            if (value === false || deviceDetection$1.isiPhone() || deviceDetection$1.isiPad()) {
6975
              return {
6976
                value: '',
6977
                valid
6978
              };
6979
            } else {
6980
              return {
6981
                value: value === true ? 'table,img,figure.image,div,video,iframe' : value,
6982
                valid
6983
              };
6984
            }
6985
          } else {
6986
            return {
6987
              valid: false,
6988
              message: 'Must be boolean or a string'
6989
            };
6990
          }
6991
        },
6992
        default: !isTouch
6993
      });
6994
      registerOption('resize_img_proportional', {
6995
        processor: 'boolean',
6996
        default: true
6997
      });
6998
      registerOption('event_root', { processor: 'object' });
6999
      registerOption('service_message', { processor: 'string' });
7000
      registerOption('theme', {
7001
        processor: value => value === false || isString(value) || isFunction(value),
7002
        default: 'silver'
7003
      });
7004
      registerOption('theme_url', { processor: 'string' });
7005
      registerOption('formats', { processor: 'object' });
7006
      registerOption('format_empty_lines', {
7007
        processor: 'boolean',
7008
        default: false
7009
      });
7010
      registerOption('format_noneditable_selector', {
7011
        processor: 'string',
7012
        default: ''
7013
      });
7014
      registerOption('preview_styles', {
7015
        processor: value => {
7016
          const valid = value === false || isString(value);
7017
          if (valid) {
7018
            return {
7019
              value: value === false ? '' : value,
7020
              valid
7021
            };
7022
          } else {
7023
            return {
7024
              valid: false,
7025
              message: 'Must be false or a string'
7026
            };
7027
          }
7028
        },
7029
        default: 'font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow'
7030
      });
7031
      registerOption('custom_ui_selector', {
7032
        processor: 'string',
7033
        default: ''
7034
      });
7035
      registerOption('hidden_input', {
7036
        processor: 'boolean',
7037
        default: true
7038
      });
7039
      registerOption('submit_patch', {
7040
        processor: 'boolean',
7041
        default: true
7042
      });
7043
      registerOption('encoding', { processor: 'string' });
7044
      registerOption('add_form_submit_trigger', {
7045
        processor: 'boolean',
7046
        default: true
7047
      });
7048
      registerOption('add_unload_trigger', {
7049
        processor: 'boolean',
7050
        default: true
7051
      });
7052
      registerOption('custom_undo_redo_levels', {
7053
        processor: 'number',
7054
        default: 0
7055
      });
7056
      registerOption('disable_nodechange', {
7057
        processor: 'boolean',
7058
        default: false
7059
      });
7060
      registerOption('readonly', {
7061
        processor: 'boolean',
7062
        default: false
7063
      });
7064
      registerOption('editable_root', {
7065
        processor: 'boolean',
7066
        default: true
7067
      });
7068
      registerOption('plugins', {
7069
        processor: 'string[]',
7070
        default: []
7071
      });
7072
      registerOption('external_plugins', { processor: 'object' });
7073
      registerOption('forced_plugins', { processor: 'string[]' });
7074
      registerOption('model', {
7075
        processor: 'string',
7076
        default: editor.hasPlugin('rtc') ? 'plugin' : 'dom'
7077
      });
7078
      registerOption('model_url', { processor: 'string' });
7079
      registerOption('block_unsupported_drop', {
7080
        processor: 'boolean',
7081
        default: true
7082
      });
7083
      registerOption('visual', {
7084
        processor: 'boolean',
7085
        default: true
7086
      });
7087
      registerOption('visual_table_class', {
7088
        processor: 'string',
7089
        default: 'mce-item-table'
7090
      });
7091
      registerOption('visual_anchor_class', {
7092
        processor: 'string',
7093
        default: 'mce-item-anchor'
7094
      });
7095
      registerOption('iframe_aria_text', {
7096
        processor: 'string',
7097
        default: 'Rich Text Area. Press ALT-0 for help.'
7098
      });
7099
      registerOption('setup', { processor: 'function' });
7100
      registerOption('init_instance_callback', { processor: 'function' });
7101
      registerOption('url_converter', {
7102
        processor: 'function',
7103
        default: editor.convertURL
7104
      });
7105
      registerOption('url_converter_scope', {
7106
        processor: 'object',
7107
        default: editor
7108
      });
7109
      registerOption('urlconverter_callback', { processor: 'function' });
7110
      registerOption('allow_conditional_comments', {
7111
        processor: 'boolean',
7112
        default: false
7113
      });
7114
      registerOption('allow_html_data_urls', {
7115
        processor: 'boolean',
7116
        default: false
7117
      });
7118
      registerOption('allow_svg_data_urls', { processor: 'boolean' });
7119
      registerOption('allow_html_in_named_anchor', {
7120
        processor: 'boolean',
7121
        default: false
7122
      });
7123
      registerOption('allow_script_urls', {
7124
        processor: 'boolean',
7125
        default: false
7126
      });
7127
      registerOption('allow_unsafe_link_target', {
7128
        processor: 'boolean',
7129
        default: false
7130
      });
7131
      registerOption('convert_fonts_to_spans', {
7132
        processor: 'boolean',
7133
        default: true,
7134
        deprecated: true
7135
      });
7136
      registerOption('fix_list_elements', {
7137
        processor: 'boolean',
7138
        default: false
7139
      });
7140
      registerOption('preserve_cdata', {
7141
        processor: 'boolean',
7142
        default: false
7143
      });
7144
      registerOption('remove_trailing_brs', {
7145
        processor: 'boolean',
7146
        default: true
7147
      });
7148
      registerOption('pad_empty_with_br', {
7149
        processor: 'boolean',
7150
        default: false
7151
      });
7152
      registerOption('inline_styles', {
7153
        processor: 'boolean',
7154
        default: true,
7155
        deprecated: true
7156
      });
7157
      registerOption('element_format', {
7158
        processor: 'string',
7159
        default: 'html'
7160
      });
7161
      registerOption('entities', { processor: 'string' });
7162
      registerOption('schema', {
7163
        processor: 'string',
7164
        default: 'html5'
7165
      });
7166
      registerOption('convert_urls', {
7167
        processor: 'boolean',
7168
        default: true
7169
      });
7170
      registerOption('relative_urls', {
7171
        processor: 'boolean',
7172
        default: true
7173
      });
7174
      registerOption('remove_script_host', {
7175
        processor: 'boolean',
7176
        default: true
7177
      });
7178
      registerOption('custom_elements', { processor: 'string' });
7179
      registerOption('extended_valid_elements', { processor: 'string' });
7180
      registerOption('invalid_elements', { processor: 'string' });
7181
      registerOption('invalid_styles', { processor: stringOrObjectProcessor });
7182
      registerOption('valid_children', { processor: 'string' });
7183
      registerOption('valid_classes', { processor: stringOrObjectProcessor });
7184
      registerOption('valid_elements', { processor: 'string' });
7185
      registerOption('valid_styles', { processor: stringOrObjectProcessor });
7186
      registerOption('verify_html', {
7187
        processor: 'boolean',
7188
        default: true
7189
      });
7190
      registerOption('auto_focus', { processor: value => isString(value) || value === true });
7191
      registerOption('browser_spellcheck', {
7192
        processor: 'boolean',
7193
        default: false
7194
      });
7195
      registerOption('protect', { processor: 'array' });
7196
      registerOption('images_file_types', {
7197
        processor: 'string',
7198
        default: 'jpeg,jpg,jpe,jfi,jif,jfif,png,gif,bmp,webp'
7199
      });
7200
      registerOption('deprecation_warnings', {
7201
        processor: 'boolean',
7202
        default: true
7203
      });
7204
      registerOption('a11y_advanced_options', {
7205
        processor: 'boolean',
7206
        default: false
7207
      });
7208
      registerOption('api_key', { processor: 'string' });
7209
      registerOption('paste_block_drop', {
7210
        processor: 'boolean',
7211
        default: false
7212
      });
7213
      registerOption('paste_data_images', {
7214
        processor: 'boolean',
7215
        default: true
7216
      });
7217
      registerOption('paste_preprocess', { processor: 'function' });
7218
      registerOption('paste_postprocess', { processor: 'function' });
7219
      registerOption('paste_webkit_styles', {
7220
        processor: 'string',
7221
        default: 'none'
7222
      });
7223
      registerOption('paste_remove_styles_if_webkit', {
7224
        processor: 'boolean',
7225
        default: true
7226
      });
7227
      registerOption('paste_merge_formats', {
7228
        processor: 'boolean',
7229
        default: true
7230
      });
7231
      registerOption('smart_paste', {
7232
        processor: 'boolean',
7233
        default: true
7234
      });
7235
      registerOption('paste_as_text', {
7236
        processor: 'boolean',
7237
        default: false
7238
      });
7239
      registerOption('paste_tab_spaces', {
7240
        processor: 'number',
7241
        default: 4
7242
      });
7243
      registerOption('text_patterns', {
7244
        processor: value => {
7245
          if (isArrayOf(value, isObject) || value === false) {
7246
            const patterns = value === false ? [] : value;
7247
            return {
7248
              value: fromRawPatterns(patterns),
7249
              valid: true
7250
            };
7251
          } else {
7252
            return {
7253
              valid: false,
7254
              message: 'Must be an array of objects or false.'
7255
            };
7256
          }
7257
        },
7258
        default: [
7259
          {
7260
            start: '*',
7261
            end: '*',
7262
            format: 'italic'
7263
          },
7264
          {
7265
            start: '**',
7266
            end: '**',
7267
            format: 'bold'
7268
          },
7269
          {
7270
            start: '#',
7271
            format: 'h1'
7272
          },
7273
          {
7274
            start: '##',
7275
            format: 'h2'
7276
          },
7277
          {
7278
            start: '###',
7279
            format: 'h3'
7280
          },
7281
          {
7282
            start: '####',
7283
            format: 'h4'
7284
          },
7285
          {
7286
            start: '#####',
7287
            format: 'h5'
7288
          },
7289
          {
7290
            start: '######',
7291
            format: 'h6'
7292
          },
7293
          {
7294
            start: '1. ',
7295
            cmd: 'InsertOrderedList'
7296
          },
7297
          {
7298
            start: '* ',
7299
            cmd: 'InsertUnorderedList'
7300
          },
7301
          {
7302
            start: '- ',
7303
            cmd: 'InsertUnorderedList'
7304
          }
7305
        ]
7306
      });
7307
      registerOption('text_patterns_lookup', {
7308
        processor: value => {
7309
          if (isFunction(value)) {
7310
            return {
7311
              value: fromRawPatternsLookup(value),
7312
              valid: true
7313
            };
7314
          } else {
7315
            return {
7316
              valid: false,
7317
              message: 'Must be a single function'
7318
            };
7319
          }
7320
        },
7321
        default: _ctx => []
7322
      });
7323
      registerOption('noneditable_class', {
7324
        processor: 'string',
7325
        default: 'mceNonEditable'
7326
      });
7327
      registerOption('editable_class', {
7328
        processor: 'string',
7329
        default: 'mceEditable'
7330
      });
7331
      registerOption('noneditable_regexp', {
7332
        processor: value => {
7333
          if (isArrayOf(value, isRegExp)) {
7334
            return {
7335
              value,
7336
              valid: true
7337
            };
7338
          } else if (isRegExp(value)) {
7339
            return {
7340
              value: [value],
7341
              valid: true
7342
            };
7343
          } else {
7344
            return {
7345
              valid: false,
7346
              message: 'Must be a RegExp or an array of RegExp.'
7347
            };
7348
          }
7349
        },
7350
        default: []
7351
      });
7352
      registerOption('table_tab_navigation', {
7353
        processor: 'boolean',
7354
        default: true
7355
      });
7356
      registerOption('highlight_on_focus', {
7357
        processor: 'boolean',
7358
        default: false
7359
      });
7360
      registerOption('xss_sanitization', {
7361
        processor: 'boolean',
7362
        default: true
7363
      });
7364
      registerOption('details_initial_state', {
7365
        processor: value => {
7366
          const valid = contains$2([
7367
            'inherited',
7368
            'collapsed',
7369
            'expanded'
7370
          ], value);
7371
          return valid ? {
7372
            value,
7373
            valid
7374
          } : {
7375
            valid: false,
7376
            message: 'Must be one of: inherited, collapsed, or expanded.'
7377
          };
7378
        },
7379
        default: 'inherited'
7380
      });
7381
      registerOption('details_serialized_state', {
7382
        processor: value => {
7383
          const valid = contains$2([
7384
            'inherited',
7385
            'collapsed',
7386
            'expanded'
7387
          ], value);
7388
          return valid ? {
7389
            value,
7390
            valid
7391
          } : {
7392
            valid: false,
7393
            message: 'Must be one of: inherited, collapsed, or expanded.'
7394
          };
7395
        },
7396
        default: 'inherited'
7397
      });
7398
      registerOption('init_content_sync', {
7399
        processor: 'boolean',
7400
        default: false
7401
      });
7402
      registerOption('newdocument_content', {
7403
        processor: 'string',
7404
        default: ''
7405
      });
7406
      registerOption('force_hex_color', {
7407
        processor: value => {
7408
          const options = [
7409
            'always',
7410
            'rgb_only',
7411
            'off'
7412
          ];
7413
          const valid = contains$2(options, value);
7414
          return valid ? {
7415
            value,
7416
            valid
7417
          } : {
7418
            valid: false,
7419
            message: `Must be one of: ${ options.join(', ') }.`
7420
          };
7421
        },
7422
        default: 'off'
7423
      });
7424
      registerOption('sandbox_iframes', {
7425
        processor: 'boolean',
7426
        default: false
7427
      });
7428
      registerOption('convert_unsafe_embeds', {
7429
        processor: 'boolean',
7430
        default: false
7431
      });
7432
      editor.on('ScriptsLoaded', () => {
7433
        registerOption('directionality', {
7434
          processor: 'string',
7435
          default: I18n.isRtl() ? 'rtl' : undefined
7436
        });
7437
        registerOption('placeholder', {
7438
          processor: 'string',
7439
          default: DOM$a.getAttrib(editor.getElement(), 'placeholder')
7440
        });
7441
      });
7442
    };
7443
    const getIframeAttrs = option('iframe_attrs');
7444
    const getDocType = option('doctype');
7445
    const getDocumentBaseUrl = option('document_base_url');
7446
    const getBodyId = option('body_id');
7447
    const getBodyClass = option('body_class');
7448
    const getContentSecurityPolicy = option('content_security_policy');
7449
    const shouldPutBrInPre$1 = option('br_in_pre');
7450
    const getForcedRootBlock = option('forced_root_block');
7451
    const getForcedRootBlockAttrs = option('forced_root_block_attrs');
7452
    const getNewlineBehavior = option('newline_behavior');
7453
    const getBrNewLineSelector = option('br_newline_selector');
7454
    const getNoNewLineSelector = option('no_newline_selector');
7455
    const shouldKeepStyles = option('keep_styles');
7456
    const shouldEndContainerOnEmptyBlock = option('end_container_on_empty_block');
7457
    const isAutomaticUploadsEnabled = option('automatic_uploads');
7458
    const shouldReuseFileName = option('images_reuse_filename');
7459
    const shouldReplaceBlobUris = option('images_replace_blob_uris');
7460
    const getIconPackName = option('icons');
7461
    const getIconsUrl = option('icons_url');
7462
    const getImageUploadUrl = option('images_upload_url');
7463
    const getImageUploadBasePath = option('images_upload_base_path');
7464
    const getImagesUploadCredentials = option('images_upload_credentials');
7465
    const getImagesUploadHandler = option('images_upload_handler');
7466
    const shouldUseContentCssCors = option('content_css_cors');
7467
    const getReferrerPolicy = option('referrer_policy');
7468
    const getLanguageCode = option('language');
7469
    const getLanguageUrl = option('language_url');
7470
    const shouldIndentUseMargin = option('indent_use_margin');
7471
    const getIndentation = option('indentation');
7472
    const getContentCss = option('content_css');
7473
    const getContentStyle = option('content_style');
7474
    const getFontCss = option('font_css');
7475
    const getDirectionality = option('directionality');
7476
    const getInlineBoundarySelector = option('inline_boundaries_selector');
7477
    const getObjectResizing = option('object_resizing');
7478
    const getResizeImgProportional = option('resize_img_proportional');
7479
    const getPlaceholder = option('placeholder');
7480
    const getEventRoot = option('event_root');
7481
    const getServiceMessage = option('service_message');
7482
    const getTheme = option('theme');
7483
    const getThemeUrl = option('theme_url');
7484
    const getModel = option('model');
7485
    const getModelUrl = option('model_url');
7486
    const isInlineBoundariesEnabled = option('inline_boundaries');
7487
    const getFormats = option('formats');
7488
    const getPreviewStyles = option('preview_styles');
7489
    const canFormatEmptyLines = option('format_empty_lines');
7490
    const getFormatNoneditableSelector = option('format_noneditable_selector');
7491
    const getCustomUiSelector = option('custom_ui_selector');
7492
    const isInline$1 = option('inline');
7493
    const hasHiddenInput = option('hidden_input');
7494
    const shouldPatchSubmit = option('submit_patch');
7495
    const shouldAddFormSubmitTrigger = option('add_form_submit_trigger');
7496
    const shouldAddUnloadTrigger = option('add_unload_trigger');
7497
    const getCustomUndoRedoLevels = option('custom_undo_redo_levels');
7498
    const shouldDisableNodeChange = option('disable_nodechange');
7499
    const isReadOnly$1 = option('readonly');
7500
    const hasEditableRoot$1 = option('editable_root');
7501
    const hasContentCssCors = option('content_css_cors');
7502
    const getPlugins = option('plugins');
7503
    const getExternalPlugins$1 = option('external_plugins');
7504
    const shouldBlockUnsupportedDrop = option('block_unsupported_drop');
7505
    const isVisualAidsEnabled = option('visual');
7506
    const getVisualAidsTableClass = option('visual_table_class');
7507
    const getVisualAidsAnchorClass = option('visual_anchor_class');
7508
    const getIframeAriaText = option('iframe_aria_text');
7509
    const getSetupCallback = option('setup');
7510
    const getInitInstanceCallback = option('init_instance_callback');
7511
    const getUrlConverterCallback = option('urlconverter_callback');
7512
    const getAutoFocus = option('auto_focus');
7513
    const shouldBrowserSpellcheck = option('browser_spellcheck');
7514
    const getProtect = option('protect');
7515
    const shouldPasteBlockDrop = option('paste_block_drop');
7516
    const shouldPasteDataImages = option('paste_data_images');
7517
    const getPastePreProcess = option('paste_preprocess');
7518
    const getPastePostProcess = option('paste_postprocess');
7519
    const getNewDocumentContent = option('newdocument_content');
7520
    const getPasteWebkitStyles = option('paste_webkit_styles');
7521
    const shouldPasteRemoveWebKitStyles = option('paste_remove_styles_if_webkit');
7522
    const shouldPasteMergeFormats = option('paste_merge_formats');
7523
    const isSmartPasteEnabled = option('smart_paste');
7524
    const isPasteAsTextEnabled = option('paste_as_text');
7525
    const getPasteTabSpaces = option('paste_tab_spaces');
7526
    const shouldAllowHtmlDataUrls = option('allow_html_data_urls');
7527
    const getTextPatterns = option('text_patterns');
7528
    const getTextPatternsLookup = option('text_patterns_lookup');
7529
    const getNonEditableClass = option('noneditable_class');
7530
    const getEditableClass = option('editable_class');
7531
    const getNonEditableRegExps = option('noneditable_regexp');
7532
    const shouldPreserveCData = option('preserve_cdata');
7533
    const shouldHighlightOnFocus = option('highlight_on_focus');
7534
    const shouldSanitizeXss = option('xss_sanitization');
7535
    const shouldUseDocumentWrite = option('init_content_sync');
7536
    const hasTextPatternsLookup = editor => editor.options.isSet('text_patterns_lookup');
7537
    const getFontStyleValues = editor => Tools.explode(editor.options.get('font_size_style_values'));
7538
    const getFontSizeClasses = editor => Tools.explode(editor.options.get('font_size_classes'));
7539
    const isEncodingXml = editor => editor.options.get('encoding') === 'xml';
7540
    const getAllowedImageFileTypes = editor => Tools.explode(editor.options.get('images_file_types'));
7541
    const hasTableTabNavigation = option('table_tab_navigation');
7542
    const getDetailsInitialState = option('details_initial_state');
7543
    const getDetailsSerializedState = option('details_serialized_state');
7544
    const shouldForceHexColor = option('force_hex_color');
7545
    const shouldSandboxIframes = option('sandbox_iframes');
7546
 
7547
    const isElement$3 = isElement$6;
7548
    const isText$5 = isText$a;
7549
    const removeNode$1 = node => {
7550
      const parentNode = node.parentNode;
7551
      if (parentNode) {
7552
        parentNode.removeChild(node);
7553
      }
7554
    };
7555
    const trimCount = text => {
7556
      const trimmedText = trim$2(text);
7557
      return {
7558
        count: text.length - trimmedText.length,
7559
        text: trimmedText
7560
      };
7561
    };
7562
    const deleteZwspChars = caretContainer => {
7563
      let idx;
7564
      while ((idx = caretContainer.data.lastIndexOf(ZWSP$1)) !== -1) {
7565
        caretContainer.deleteData(idx, 1);
7566
      }
7567
    };
7568
    const removeUnchanged = (caretContainer, pos) => {
7569
      remove$3(caretContainer);
7570
      return pos;
7571
    };
7572
    const removeTextAndReposition = (caretContainer, pos) => {
7573
      const before = trimCount(caretContainer.data.substr(0, pos.offset()));
7574
      const after = trimCount(caretContainer.data.substr(pos.offset()));
7575
      const text = before.text + after.text;
7576
      if (text.length > 0) {
7577
        deleteZwspChars(caretContainer);
7578
        return CaretPosition(caretContainer, pos.offset() - before.count);
7579
      } else {
7580
        return pos;
7581
      }
7582
    };
7583
    const removeElementAndReposition = (caretContainer, pos) => {
7584
      const parentNode = pos.container();
7585
      const newPosition = indexOf$1(from(parentNode.childNodes), caretContainer).map(index => {
7586
        return index < pos.offset() ? CaretPosition(parentNode, pos.offset() - 1) : pos;
7587
      }).getOr(pos);
7588
      remove$3(caretContainer);
7589
      return newPosition;
7590
    };
7591
    const removeTextCaretContainer = (caretContainer, pos) => isText$5(caretContainer) && pos.container() === caretContainer ? removeTextAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
7592
    const removeElementCaretContainer = (caretContainer, pos) => pos.container() === caretContainer.parentNode ? removeElementAndReposition(caretContainer, pos) : removeUnchanged(caretContainer, pos);
7593
    const removeAndReposition = (container, pos) => CaretPosition.isTextPosition(pos) ? removeTextCaretContainer(container, pos) : removeElementCaretContainer(container, pos);
7594
    const remove$3 = caretContainerNode => {
7595
      if (isElement$3(caretContainerNode) && isCaretContainer$2(caretContainerNode)) {
7596
        if (hasContent(caretContainerNode)) {
7597
          caretContainerNode.removeAttribute('data-mce-caret');
7598
        } else {
7599
          removeNode$1(caretContainerNode);
7600
        }
7601
      }
7602
      if (isText$5(caretContainerNode)) {
7603
        deleteZwspChars(caretContainerNode);
7604
        if (caretContainerNode.data.length === 0) {
7605
          removeNode$1(caretContainerNode);
7606
        }
7607
      }
7608
    };
7609
 
7610
    const isContentEditableFalse$8 = isContentEditableFalse$b;
7611
    const isMedia$1 = isMedia$2;
7612
    const isTableCell$1 = isTableCell$3;
7613
    const inlineFakeCaretSelector = '*[contentEditable=false],video,audio,embed,object';
7614
    const getAbsoluteClientRect = (root, element, before) => {
7615
      const clientRect = collapse(element.getBoundingClientRect(), before);
7616
      let scrollX;
7617
      let scrollY;
7618
      if (root.tagName === 'BODY') {
7619
        const docElm = root.ownerDocument.documentElement;
7620
        scrollX = root.scrollLeft || docElm.scrollLeft;
7621
        scrollY = root.scrollTop || docElm.scrollTop;
7622
      } else {
7623
        const rootRect = root.getBoundingClientRect();
7624
        scrollX = root.scrollLeft - rootRect.left;
7625
        scrollY = root.scrollTop - rootRect.top;
7626
      }
7627
      clientRect.left += scrollX;
7628
      clientRect.right += scrollX;
7629
      clientRect.top += scrollY;
7630
      clientRect.bottom += scrollY;
7631
      clientRect.width = 1;
7632
      let margin = element.offsetWidth - element.clientWidth;
7633
      if (margin > 0) {
7634
        if (before) {
7635
          margin *= -1;
7636
        }
7637
        clientRect.left += margin;
7638
        clientRect.right += margin;
7639
      }
7640
      return clientRect;
7641
    };
7642
    const trimInlineCaretContainers = root => {
7643
      var _a, _b;
7644
      const fakeCaretTargetNodes = descendants(SugarElement.fromDom(root), inlineFakeCaretSelector);
7645
      for (let i = 0; i < fakeCaretTargetNodes.length; i++) {
7646
        const node = fakeCaretTargetNodes[i].dom;
7647
        let sibling = node.previousSibling;
7648
        if (endsWithCaretContainer$1(sibling)) {
7649
          const data = sibling.data;
7650
          if (data.length === 1) {
7651
            (_a = sibling.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(sibling);
7652
          } else {
7653
            sibling.deleteData(data.length - 1, 1);
7654
          }
7655
        }
7656
        sibling = node.nextSibling;
7657
        if (startsWithCaretContainer$1(sibling)) {
7658
          const data = sibling.data;
7659
          if (data.length === 1) {
7660
            (_b = sibling.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(sibling);
7661
          } else {
7662
            sibling.deleteData(0, 1);
7663
          }
7664
        }
7665
      }
7666
    };
7667
    const FakeCaret = (editor, root, isBlock, hasFocus) => {
7668
      const lastVisualCaret = value$2();
7669
      let cursorInterval;
7670
      let caretContainerNode;
7671
      const caretBlock = getForcedRootBlock(editor);
7672
      const dom = editor.dom;
7673
      const show = (before, element) => {
7674
        let rng;
7675
        hide();
7676
        if (isTableCell$1(element)) {
7677
          return null;
7678
        }
7679
        if (isBlock(element)) {
7680
          const caretContainer = insertBlock(caretBlock, element, before);
7681
          const clientRect = getAbsoluteClientRect(root, element, before);
7682
          dom.setStyle(caretContainer, 'top', clientRect.top);
7683
          caretContainerNode = caretContainer;
7684
          const caret = dom.create('div', {
7685
            'class': 'mce-visual-caret',
7686
            'data-mce-bogus': 'all'
7687
          });
7688
          dom.setStyles(caret, { ...clientRect });
7689
          dom.add(root, caret);
7690
          lastVisualCaret.set({
7691
            caret,
7692
            element,
7693
            before
7694
          });
7695
          if (before) {
7696
            dom.addClass(caret, 'mce-visual-caret-before');
7697
          }
7698
          startBlink();
7699
          rng = element.ownerDocument.createRange();
7700
          rng.setStart(caretContainer, 0);
7701
          rng.setEnd(caretContainer, 0);
7702
        } else {
7703
          caretContainerNode = insertInline$1(element, before);
7704
          rng = element.ownerDocument.createRange();
7705
          if (isInlineFakeCaretTarget(caretContainerNode.nextSibling)) {
7706
            rng.setStart(caretContainerNode, 0);
7707
            rng.setEnd(caretContainerNode, 0);
7708
          } else {
7709
            rng.setStart(caretContainerNode, 1);
7710
            rng.setEnd(caretContainerNode, 1);
7711
          }
7712
          return rng;
7713
        }
7714
        return rng;
7715
      };
7716
      const hide = () => {
7717
        trimInlineCaretContainers(root);
7718
        if (caretContainerNode) {
7719
          remove$3(caretContainerNode);
7720
          caretContainerNode = null;
7721
        }
7722
        lastVisualCaret.on(caretState => {
7723
          dom.remove(caretState.caret);
7724
          lastVisualCaret.clear();
7725
        });
7726
        if (cursorInterval) {
7727
          clearInterval(cursorInterval);
7728
          cursorInterval = undefined;
7729
        }
7730
      };
7731
      const startBlink = () => {
7732
        cursorInterval = setInterval(() => {
7733
          lastVisualCaret.on(caretState => {
7734
            if (hasFocus()) {
7735
              dom.toggleClass(caretState.caret, 'mce-visual-caret-hidden');
7736
            } else {
7737
              dom.addClass(caretState.caret, 'mce-visual-caret-hidden');
7738
            }
7739
          });
7740
        }, 500);
7741
      };
7742
      const reposition = () => {
7743
        lastVisualCaret.on(caretState => {
7744
          const clientRect = getAbsoluteClientRect(root, caretState.element, caretState.before);
7745
          dom.setStyles(caretState.caret, { ...clientRect });
7746
        });
7747
      };
7748
      const destroy = () => clearInterval(cursorInterval);
7749
      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;' + '}';
7750
      return {
7751
        show,
7752
        hide,
7753
        getCss,
7754
        reposition,
7755
        destroy
7756
      };
7757
    };
7758
    const isFakeCaretTableBrowser = () => Env.browser.isFirefox();
7759
    const isInlineFakeCaretTarget = node => isContentEditableFalse$8(node) || isMedia$1(node);
7760
    const isFakeCaretTarget = node => {
7761
      const isTarget = isInlineFakeCaretTarget(node) || isTable$2(node) && isFakeCaretTableBrowser();
7762
      return isTarget && parentElement(SugarElement.fromDom(node)).exists(isEditable$2);
7763
    };
7764
 
7765
    const isContentEditableTrue$1 = isContentEditableTrue$3;
7766
    const isContentEditableFalse$7 = isContentEditableFalse$b;
7767
    const isMedia = isMedia$2;
7768
    const isBlockLike = matchStyleValues('display', 'block table table-cell table-caption list-item');
7769
    const isCaretContainer = isCaretContainer$2;
7770
    const isCaretContainerBlock = isCaretContainerBlock$1;
7771
    const isElement$2 = isElement$6;
7772
    const isText$4 = isText$a;
7773
    const isCaretCandidate$1 = isCaretCandidate$3;
7774
    const isForwards = direction => direction > 0;
7775
    const isBackwards = direction => direction < 0;
7776
    const skipCaretContainers = (walk, shallow) => {
7777
      let node;
7778
      while (node = walk(shallow)) {
7779
        if (!isCaretContainerBlock(node)) {
7780
          return node;
7781
        }
7782
      }
7783
      return null;
7784
    };
7785
    const findNode = (node, direction, predicateFn, rootNode, shallow) => {
7786
      const walker = new DomTreeWalker(node, rootNode);
7787
      const isCefOrCaretContainer = isContentEditableFalse$7(node) || isCaretContainerBlock(node);
7788
      let tempNode;
7789
      if (isBackwards(direction)) {
7790
        if (isCefOrCaretContainer) {
7791
          tempNode = skipCaretContainers(walker.prev.bind(walker), true);
7792
          if (predicateFn(tempNode)) {
7793
            return tempNode;
7794
          }
7795
        }
7796
        while (tempNode = skipCaretContainers(walker.prev.bind(walker), shallow)) {
7797
          if (predicateFn(tempNode)) {
7798
            return tempNode;
7799
          }
7800
        }
7801
      }
7802
      if (isForwards(direction)) {
7803
        if (isCefOrCaretContainer) {
7804
          tempNode = skipCaretContainers(walker.next.bind(walker), true);
7805
          if (predicateFn(tempNode)) {
7806
            return tempNode;
7807
          }
7808
        }
7809
        while (tempNode = skipCaretContainers(walker.next.bind(walker), shallow)) {
7810
          if (predicateFn(tempNode)) {
7811
            return tempNode;
7812
          }
7813
        }
7814
      }
7815
      return null;
7816
    };
7817
    const getEditingHost = (node, rootNode) => {
7818
      const isCETrue = node => isContentEditableTrue$1(node.dom);
7819
      const isRoot = node => node.dom === rootNode;
7820
      return ancestor$4(SugarElement.fromDom(node), isCETrue, isRoot).map(elm => elm.dom).getOr(rootNode);
7821
    };
7822
    const getParentBlock$3 = (node, rootNode) => {
7823
      while (node && node !== rootNode) {
7824
        if (isBlockLike(node)) {
7825
          return node;
7826
        }
7827
        node = node.parentNode;
7828
      }
7829
      return null;
7830
    };
7831
    const isInSameBlock = (caretPosition1, caretPosition2, rootNode) => getParentBlock$3(caretPosition1.container(), rootNode) === getParentBlock$3(caretPosition2.container(), rootNode);
7832
    const getChildNodeAtRelativeOffset = (relativeOffset, caretPosition) => {
7833
      if (!caretPosition) {
7834
        return Optional.none();
7835
      }
7836
      const container = caretPosition.container();
7837
      const offset = caretPosition.offset();
7838
      if (!isElement$2(container)) {
7839
        return Optional.none();
7840
      }
7841
      return Optional.from(container.childNodes[offset + relativeOffset]);
7842
    };
7843
    const beforeAfter = (before, node) => {
7844
      var _a;
7845
      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
7846
      const range = doc.createRange();
7847
      if (before) {
7848
        range.setStartBefore(node);
7849
        range.setEndBefore(node);
7850
      } else {
7851
        range.setStartAfter(node);
7852
        range.setEndAfter(node);
7853
      }
7854
      return range;
7855
    };
7856
    const isNodesInSameBlock = (root, node1, node2) => getParentBlock$3(node1, root) === getParentBlock$3(node2, root);
7857
    const lean = (left, root, node) => {
7858
      const siblingName = left ? 'previousSibling' : 'nextSibling';
7859
      let tempNode = node;
7860
      while (tempNode && tempNode !== root) {
7861
        let sibling = tempNode[siblingName];
7862
        if (sibling && isCaretContainer(sibling)) {
7863
          sibling = sibling[siblingName];
7864
        }
7865
        if (isContentEditableFalse$7(sibling) || isMedia(sibling)) {
7866
          if (isNodesInSameBlock(root, sibling, tempNode)) {
7867
            return sibling;
7868
          }
7869
          break;
7870
        }
7871
        if (isCaretCandidate$1(sibling)) {
7872
          break;
7873
        }
7874
        tempNode = tempNode.parentNode;
7875
      }
7876
      return null;
7877
    };
7878
    const before$2 = curry(beforeAfter, true);
7879
    const after$2 = curry(beforeAfter, false);
7880
    const normalizeRange = (direction, root, range) => {
7881
      let node;
7882
      const leanLeft = curry(lean, true, root);
7883
      const leanRight = curry(lean, false, root);
7884
      const container = range.startContainer;
7885
      const offset = range.startOffset;
7886
      if (isCaretContainerBlock$1(container)) {
7887
        const block = isText$4(container) ? container.parentNode : container;
7888
        const location = block.getAttribute('data-mce-caret');
7889
        if (location === 'before') {
7890
          node = block.nextSibling;
7891
          if (isFakeCaretTarget(node)) {
7892
            return before$2(node);
7893
          }
7894
        }
7895
        if (location === 'after') {
7896
          node = block.previousSibling;
7897
          if (isFakeCaretTarget(node)) {
7898
            return after$2(node);
7899
          }
7900
        }
7901
      }
7902
      if (!range.collapsed) {
7903
        return range;
7904
      }
7905
      if (isText$a(container)) {
7906
        if (isCaretContainer(container)) {
7907
          if (direction === 1) {
7908
            node = leanRight(container);
7909
            if (node) {
7910
              return before$2(node);
7911
            }
7912
            node = leanLeft(container);
7913
            if (node) {
7914
              return after$2(node);
7915
            }
7916
          }
7917
          if (direction === -1) {
7918
            node = leanLeft(container);
7919
            if (node) {
7920
              return after$2(node);
7921
            }
7922
            node = leanRight(container);
7923
            if (node) {
7924
              return before$2(node);
7925
            }
7926
          }
7927
          return range;
7928
        }
7929
        if (endsWithCaretContainer$1(container) && offset >= container.data.length - 1) {
7930
          if (direction === 1) {
7931
            node = leanRight(container);
7932
            if (node) {
7933
              return before$2(node);
7934
            }
7935
          }
7936
          return range;
7937
        }
7938
        if (startsWithCaretContainer$1(container) && offset <= 1) {
7939
          if (direction === -1) {
7940
            node = leanLeft(container);
7941
            if (node) {
7942
              return after$2(node);
7943
            }
7944
          }
7945
          return range;
7946
        }
7947
        if (offset === container.data.length) {
7948
          node = leanRight(container);
7949
          if (node) {
7950
            return before$2(node);
7951
          }
7952
          return range;
7953
        }
7954
        if (offset === 0) {
7955
          node = leanLeft(container);
7956
          if (node) {
7957
            return after$2(node);
7958
          }
7959
          return range;
7960
        }
7961
      }
7962
      return range;
7963
    };
7964
    const getRelativeCefElm = (forward, caretPosition) => getChildNodeAtRelativeOffset(forward ? 0 : -1, caretPosition).filter(isContentEditableFalse$7);
7965
    const getNormalizedRangeEndPoint = (direction, root, range) => {
7966
      const normalizedRange = normalizeRange(direction, root, range);
7967
      return direction === -1 ? CaretPosition.fromRangeStart(normalizedRange) : CaretPosition.fromRangeEnd(normalizedRange);
7968
    };
7969
    const getElementFromPosition = pos => Optional.from(pos.getNode()).map(SugarElement.fromDom);
7970
    const getElementFromPrevPosition = pos => Optional.from(pos.getNode(true)).map(SugarElement.fromDom);
7971
    const getVisualCaretPosition = (walkFn, caretPosition) => {
7972
      let pos = caretPosition;
7973
      while (pos = walkFn(pos)) {
7974
        if (pos.isVisible()) {
7975
          return pos;
7976
        }
7977
      }
7978
      return pos;
7979
    };
7980
    const isMoveInsideSameBlock = (from, to) => {
7981
      const inSameBlock = isInSameBlock(from, to);
7982
      if (!inSameBlock && isBr$6(from.getNode())) {
7983
        return true;
7984
      }
7985
      return inSameBlock;
7986
    };
7987
 
7988
    var HDirection;
7989
    (function (HDirection) {
7990
      HDirection[HDirection['Backwards'] = -1] = 'Backwards';
7991
      HDirection[HDirection['Forwards'] = 1] = 'Forwards';
7992
    }(HDirection || (HDirection = {})));
7993
    const isContentEditableFalse$6 = isContentEditableFalse$b;
7994
    const isText$3 = isText$a;
7995
    const isElement$1 = isElement$6;
7996
    const isBr$2 = isBr$6;
7997
    const isCaretCandidate = isCaretCandidate$3;
7998
    const isAtomic = isAtomic$1;
7999
    const isEditableCaretCandidate = isEditableCaretCandidate$1;
8000
    const getParents$3 = (node, root) => {
8001
      const parents = [];
8002
      let tempNode = node;
8003
      while (tempNode && tempNode !== root) {
8004
        parents.push(tempNode);
8005
        tempNode = tempNode.parentNode;
8006
      }
8007
      return parents;
8008
    };
8009
    const nodeAtIndex = (container, offset) => {
8010
      if (container.hasChildNodes() && offset < container.childNodes.length) {
8011
        return container.childNodes[offset];
8012
      }
8013
      return null;
8014
    };
8015
    const getCaretCandidatePosition = (direction, node) => {
8016
      if (isForwards(direction)) {
8017
        if (isCaretCandidate(node.previousSibling) && !isText$3(node.previousSibling)) {
8018
          return CaretPosition.before(node);
8019
        }
8020
        if (isText$3(node)) {
8021
          return CaretPosition(node, 0);
8022
        }
8023
      }
8024
      if (isBackwards(direction)) {
8025
        if (isCaretCandidate(node.nextSibling) && !isText$3(node.nextSibling)) {
8026
          return CaretPosition.after(node);
8027
        }
8028
        if (isText$3(node)) {
8029
          return CaretPosition(node, node.data.length);
8030
        }
8031
      }
8032
      if (isBackwards(direction)) {
8033
        if (isBr$2(node)) {
8034
          return CaretPosition.before(node);
8035
        }
8036
        return CaretPosition.after(node);
8037
      }
8038
      return CaretPosition.before(node);
8039
    };
8040
    const moveForwardFromBr = (root, nextNode) => {
8041
      const nextSibling = nextNode.nextSibling;
8042
      if (nextSibling && isCaretCandidate(nextSibling)) {
8043
        if (isText$3(nextSibling)) {
8044
          return CaretPosition(nextSibling, 0);
8045
        } else {
8046
          return CaretPosition.before(nextSibling);
8047
        }
8048
      } else {
8049
        return findCaretPosition$1(HDirection.Forwards, CaretPosition.after(nextNode), root);
8050
      }
8051
    };
8052
    const findCaretPosition$1 = (direction, startPos, root) => {
8053
      let node;
8054
      let nextNode;
8055
      let innerNode;
8056
      let caretPosition;
8057
      if (!isElement$1(root) || !startPos) {
8058
        return null;
8059
      }
8060
      if (startPos.isEqual(CaretPosition.after(root)) && root.lastChild) {
8061
        caretPosition = CaretPosition.after(root.lastChild);
8062
        if (isBackwards(direction) && isCaretCandidate(root.lastChild) && isElement$1(root.lastChild)) {
8063
          return isBr$2(root.lastChild) ? CaretPosition.before(root.lastChild) : caretPosition;
8064
        }
8065
      } else {
8066
        caretPosition = startPos;
8067
      }
8068
      const container = caretPosition.container();
8069
      let offset = caretPosition.offset();
8070
      if (isText$3(container)) {
8071
        if (isBackwards(direction) && offset > 0) {
8072
          return CaretPosition(container, --offset);
8073
        }
8074
        if (isForwards(direction) && offset < container.length) {
8075
          return CaretPosition(container, ++offset);
8076
        }
8077
        node = container;
8078
      } else {
8079
        if (isBackwards(direction) && offset > 0) {
8080
          nextNode = nodeAtIndex(container, offset - 1);
8081
          if (isCaretCandidate(nextNode)) {
8082
            if (!isAtomic(nextNode)) {
8083
              innerNode = findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
8084
              if (innerNode) {
8085
                if (isText$3(innerNode)) {
8086
                  return CaretPosition(innerNode, innerNode.data.length);
8087
                }
8088
                return CaretPosition.after(innerNode);
8089
              }
8090
            }
8091
            if (isText$3(nextNode)) {
8092
              return CaretPosition(nextNode, nextNode.data.length);
8093
            }
8094
            return CaretPosition.before(nextNode);
8095
          }
8096
        }
8097
        if (isForwards(direction) && offset < container.childNodes.length) {
8098
          nextNode = nodeAtIndex(container, offset);
8099
          if (isCaretCandidate(nextNode)) {
8100
            if (isBr$2(nextNode)) {
8101
              return moveForwardFromBr(root, nextNode);
8102
            }
8103
            if (!isAtomic(nextNode)) {
8104
              innerNode = findNode(nextNode, direction, isEditableCaretCandidate, nextNode);
8105
              if (innerNode) {
8106
                if (isText$3(innerNode)) {
8107
                  return CaretPosition(innerNode, 0);
8108
                }
8109
                return CaretPosition.before(innerNode);
8110
              }
8111
            }
8112
            if (isText$3(nextNode)) {
8113
              return CaretPosition(nextNode, 0);
8114
            }
8115
            return CaretPosition.after(nextNode);
8116
          }
8117
        }
8118
        node = nextNode ? nextNode : caretPosition.getNode();
8119
      }
8120
      if (node && (isForwards(direction) && caretPosition.isAtEnd() || isBackwards(direction) && caretPosition.isAtStart())) {
8121
        node = findNode(node, direction, always, root, true);
8122
        if (isEditableCaretCandidate(node, root)) {
8123
          return getCaretCandidatePosition(direction, node);
8124
        }
8125
      }
8126
      nextNode = node ? findNode(node, direction, isEditableCaretCandidate, root) : node;
8127
      const rootContentEditableFalseElm = last$2(filter$5(getParents$3(container, root), isContentEditableFalse$6));
8128
      if (rootContentEditableFalseElm && (!nextNode || !rootContentEditableFalseElm.contains(nextNode))) {
8129
        if (isForwards(direction)) {
8130
          caretPosition = CaretPosition.after(rootContentEditableFalseElm);
8131
        } else {
8132
          caretPosition = CaretPosition.before(rootContentEditableFalseElm);
8133
        }
8134
        return caretPosition;
8135
      }
8136
      if (nextNode) {
8137
        return getCaretCandidatePosition(direction, nextNode);
8138
      }
8139
      return null;
8140
    };
8141
    const CaretWalker = root => ({
8142
      next: caretPosition => {
8143
        return findCaretPosition$1(HDirection.Forwards, caretPosition, root);
8144
      },
8145
      prev: caretPosition => {
8146
        return findCaretPosition$1(HDirection.Backwards, caretPosition, root);
8147
      }
8148
    });
8149
 
8150
    const walkToPositionIn = (forward, root, start) => {
8151
      const position = forward ? CaretPosition.before(start) : CaretPosition.after(start);
8152
      return fromPosition(forward, root, position);
8153
    };
8154
    const afterElement = node => isBr$6(node) ? CaretPosition.before(node) : CaretPosition.after(node);
8155
    const isBeforeOrStart = position => {
8156
      if (CaretPosition.isTextPosition(position)) {
8157
        return position.offset() === 0;
8158
      } else {
8159
        return isCaretCandidate$3(position.getNode());
8160
      }
8161
    };
8162
    const isAfterOrEnd = position => {
8163
      if (CaretPosition.isTextPosition(position)) {
8164
        const container = position.container();
8165
        return position.offset() === container.data.length;
8166
      } else {
8167
        return isCaretCandidate$3(position.getNode(true));
8168
      }
8169
    };
8170
    const isBeforeAfterSameElement = (from, to) => !CaretPosition.isTextPosition(from) && !CaretPosition.isTextPosition(to) && from.getNode() === to.getNode(true);
8171
    const isAtBr = position => !CaretPosition.isTextPosition(position) && isBr$6(position.getNode());
8172
    const shouldSkipPosition = (forward, from, to) => {
8173
      if (forward) {
8174
        return !isBeforeAfterSameElement(from, to) && !isAtBr(from) && isAfterOrEnd(from) && isBeforeOrStart(to);
8175
      } else {
8176
        return !isBeforeAfterSameElement(to, from) && isBeforeOrStart(from) && isAfterOrEnd(to);
8177
      }
8178
    };
8179
    const fromPosition = (forward, root, pos) => {
8180
      const walker = CaretWalker(root);
8181
      return Optional.from(forward ? walker.next(pos) : walker.prev(pos));
8182
    };
8183
    const navigate = (forward, root, from) => fromPosition(forward, root, from).bind(to => {
8184
      if (isInSameBlock(from, to, root) && shouldSkipPosition(forward, from, to)) {
8185
        return fromPosition(forward, root, to);
8186
      } else {
8187
        return Optional.some(to);
8188
      }
8189
    });
8190
    const navigateIgnore = (forward, root, from, ignoreFilter) => navigate(forward, root, from).bind(pos => ignoreFilter(pos) ? navigateIgnore(forward, root, pos, ignoreFilter) : Optional.some(pos));
8191
    const positionIn = (forward, element) => {
8192
      const startNode = forward ? element.firstChild : element.lastChild;
8193
      if (isText$a(startNode)) {
8194
        return Optional.some(CaretPosition(startNode, forward ? 0 : startNode.data.length));
8195
      } else if (startNode) {
8196
        if (isCaretCandidate$3(startNode)) {
8197
          return Optional.some(forward ? CaretPosition.before(startNode) : afterElement(startNode));
8198
        } else {
8199
          return walkToPositionIn(forward, element, startNode);
8200
        }
8201
      } else {
8202
        return Optional.none();
8203
      }
8204
    };
8205
    const nextPosition = curry(fromPosition, true);
8206
    const prevPosition = curry(fromPosition, false);
8207
    const firstPositionIn = curry(positionIn, true);
8208
    const lastPositionIn = curry(positionIn, false);
8209
 
8210
    const CARET_ID = '_mce_caret';
8211
    const isCaretNode = node => isElement$6(node) && node.id === CARET_ID;
8212
    const getParentCaretContainer = (body, node) => {
8213
      let currentNode = node;
8214
      while (currentNode && currentNode !== body) {
8215
        if (isCaretNode(currentNode)) {
8216
          return currentNode;
8217
        }
8218
        currentNode = currentNode.parentNode;
8219
      }
8220
      return null;
8221
    };
8222
 
8223
    const isStringPathBookmark = bookmark => isString(bookmark.start);
8224
    const isRangeBookmark = bookmark => has$2(bookmark, 'rng');
8225
    const isIdBookmark = bookmark => has$2(bookmark, 'id');
8226
    const isIndexBookmark = bookmark => has$2(bookmark, 'name');
8227
    const isPathBookmark = bookmark => Tools.isArray(bookmark.start);
8228
 
8229
    const isForwardBookmark = bookmark => !isIndexBookmark(bookmark) && isBoolean(bookmark.forward) ? bookmark.forward : true;
8230
    const addBogus = (dom, node) => {
8231
      if (isElement$6(node) && dom.isBlock(node) && !node.innerHTML) {
8232
        node.innerHTML = '<br data-mce-bogus="1" />';
8233
      }
8234
      return node;
8235
    };
8236
    const resolveCaretPositionBookmark = (dom, bookmark) => {
8237
      const startPos = Optional.from(resolve$1(dom.getRoot(), bookmark.start));
8238
      const endPos = Optional.from(resolve$1(dom.getRoot(), bookmark.end));
8239
      return lift2(startPos, endPos, (start, end) => {
8240
        const range = dom.createRng();
8241
        range.setStart(start.container(), start.offset());
8242
        range.setEnd(end.container(), end.offset());
8243
        return {
8244
          range,
8245
          forward: isForwardBookmark(bookmark)
8246
        };
8247
      });
8248
    };
8249
    const insertZwsp = (node, rng) => {
8250
      var _a;
8251
      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
8252
      const textNode = doc.createTextNode(ZWSP$1);
8253
      node.appendChild(textNode);
8254
      rng.setStart(textNode, 0);
8255
      rng.setEnd(textNode, 0);
8256
    };
8257
    const isEmpty$1 = node => !node.hasChildNodes();
8258
    const tryFindRangePosition = (node, rng) => lastPositionIn(node).fold(never, pos => {
8259
      rng.setStart(pos.container(), pos.offset());
8260
      rng.setEnd(pos.container(), pos.offset());
8261
      return true;
8262
    });
8263
    const padEmptyCaretContainer = (root, node, rng) => {
8264
      if (isEmpty$1(node) && getParentCaretContainer(root, node)) {
8265
        insertZwsp(node, rng);
8266
        return true;
8267
      } else {
8268
        return false;
8269
      }
8270
    };
8271
    const setEndPoint = (dom, start, bookmark, rng) => {
8272
      const point = bookmark[start ? 'start' : 'end'];
8273
      const root = dom.getRoot();
8274
      if (point) {
8275
        let node = root;
8276
        let offset = point[0];
8277
        for (let i = point.length - 1; node && i >= 1; i--) {
8278
          const children = node.childNodes;
8279
          if (padEmptyCaretContainer(root, node, rng)) {
8280
            return true;
8281
          }
8282
          if (point[i] > children.length - 1) {
8283
            if (padEmptyCaretContainer(root, node, rng)) {
8284
              return true;
8285
            }
8286
            return tryFindRangePosition(node, rng);
8287
          }
8288
          node = children[point[i]];
8289
        }
8290
        if (isText$a(node)) {
8291
          offset = Math.min(point[0], node.data.length);
8292
        }
8293
        if (isElement$6(node)) {
8294
          offset = Math.min(point[0], node.childNodes.length);
8295
        }
8296
        if (start) {
8297
          rng.setStart(node, offset);
8298
        } else {
8299
          rng.setEnd(node, offset);
8300
        }
8301
      }
8302
      return true;
8303
    };
8304
    const isValidTextNode = node => isText$a(node) && node.data.length > 0;
8305
    const restoreEndPoint = (dom, suffix, bookmark) => {
8306
      const marker = dom.get(bookmark.id + '_' + suffix);
8307
      const markerParent = marker === null || marker === void 0 ? void 0 : marker.parentNode;
8308
      const keep = bookmark.keep;
8309
      if (marker && markerParent) {
8310
        let container;
8311
        let offset;
8312
        if (suffix === 'start') {
8313
          if (!keep) {
8314
            container = markerParent;
8315
            offset = dom.nodeIndex(marker);
8316
          } else {
8317
            if (marker.hasChildNodes()) {
8318
              container = marker.firstChild;
8319
              offset = 1;
8320
            } else if (isValidTextNode(marker.nextSibling)) {
8321
              container = marker.nextSibling;
8322
              offset = 0;
8323
            } else if (isValidTextNode(marker.previousSibling)) {
8324
              container = marker.previousSibling;
8325
              offset = marker.previousSibling.data.length;
8326
            } else {
8327
              container = markerParent;
8328
              offset = dom.nodeIndex(marker) + 1;
8329
            }
8330
          }
8331
        } else {
8332
          if (!keep) {
8333
            container = markerParent;
8334
            offset = dom.nodeIndex(marker);
8335
          } else {
8336
            if (marker.hasChildNodes()) {
8337
              container = marker.firstChild;
8338
              offset = 1;
8339
            } else if (isValidTextNode(marker.previousSibling)) {
8340
              container = marker.previousSibling;
8341
              offset = marker.previousSibling.data.length;
8342
            } else {
8343
              container = markerParent;
8344
              offset = dom.nodeIndex(marker);
8345
            }
8346
          }
8347
        }
8348
        if (!keep) {
8349
          const prev = marker.previousSibling;
8350
          const next = marker.nextSibling;
8351
          Tools.each(Tools.grep(marker.childNodes), node => {
8352
            if (isText$a(node)) {
8353
              node.data = node.data.replace(/\uFEFF/g, '');
8354
            }
8355
          });
8356
          let otherMarker;
8357
          while (otherMarker = dom.get(bookmark.id + '_' + suffix)) {
8358
            dom.remove(otherMarker, true);
8359
          }
8360
          if (isText$a(next) && isText$a(prev) && !Env.browser.isOpera()) {
8361
            const idx = prev.data.length;
8362
            prev.appendData(next.data);
8363
            dom.remove(next);
8364
            container = prev;
8365
            offset = idx;
8366
          }
8367
        }
8368
        return Optional.some(CaretPosition(container, offset));
8369
      } else {
8370
        return Optional.none();
8371
      }
8372
    };
8373
    const resolvePaths = (dom, bookmark) => {
8374
      const range = dom.createRng();
8375
      if (setEndPoint(dom, true, bookmark, range) && setEndPoint(dom, false, bookmark, range)) {
8376
        return Optional.some({
8377
          range,
8378
          forward: isForwardBookmark(bookmark)
8379
        });
8380
      } else {
8381
        return Optional.none();
8382
      }
8383
    };
8384
    const resolveId = (dom, bookmark) => {
8385
      const startPos = restoreEndPoint(dom, 'start', bookmark);
8386
      const endPos = restoreEndPoint(dom, 'end', bookmark);
8387
      return lift2(startPos, endPos.or(startPos), (spos, epos) => {
8388
        const range = dom.createRng();
8389
        range.setStart(addBogus(dom, spos.container()), spos.offset());
8390
        range.setEnd(addBogus(dom, epos.container()), epos.offset());
8391
        return {
8392
          range,
8393
          forward: isForwardBookmark(bookmark)
8394
        };
8395
      });
8396
    };
8397
    const resolveIndex = (dom, bookmark) => Optional.from(dom.select(bookmark.name)[bookmark.index]).map(elm => {
8398
      const range = dom.createRng();
8399
      range.selectNode(elm);
8400
      return {
8401
        range,
8402
        forward: true
8403
      };
8404
    });
8405
    const resolve = (selection, bookmark) => {
8406
      const dom = selection.dom;
8407
      if (bookmark) {
8408
        if (isPathBookmark(bookmark)) {
8409
          return resolvePaths(dom, bookmark);
8410
        } else if (isStringPathBookmark(bookmark)) {
8411
          return resolveCaretPositionBookmark(dom, bookmark);
8412
        } else if (isIdBookmark(bookmark)) {
8413
          return resolveId(dom, bookmark);
8414
        } else if (isIndexBookmark(bookmark)) {
8415
          return resolveIndex(dom, bookmark);
8416
        } else if (isRangeBookmark(bookmark)) {
8417
          return Optional.some({
8418
            range: bookmark.rng,
8419
            forward: isForwardBookmark(bookmark)
8420
          });
8421
        }
8422
      }
8423
      return Optional.none();
8424
    };
8425
 
8426
    const getBookmark$1 = (selection, type, normalized) => {
8427
      return getBookmark$2(selection, type, normalized);
8428
    };
8429
    const moveToBookmark = (selection, bookmark) => {
8430
      resolve(selection, bookmark).each(({range, forward}) => {
8431
        selection.setRng(range, forward);
8432
      });
8433
    };
8434
    const isBookmarkNode$1 = node => {
8435
      return isElement$6(node) && node.tagName === 'SPAN' && node.getAttribute('data-mce-type') === 'bookmark';
8436
    };
8437
 
8438
    const is = expected => actual => expected === actual;
8439
    const isNbsp = is(nbsp);
8440
    const isWhiteSpace = chr => chr !== '' && ' \f\n\r\t\x0B'.indexOf(chr) !== -1;
8441
    const isContent = chr => !isWhiteSpace(chr) && !isNbsp(chr) && !isZwsp$2(chr);
8442
 
8443
    const getRanges$1 = selection => {
8444
      const ranges = [];
8445
      if (selection) {
8446
        for (let i = 0; i < selection.rangeCount; i++) {
8447
          ranges.push(selection.getRangeAt(i));
8448
        }
8449
      }
8450
      return ranges;
8451
    };
8452
    const getSelectedNodes = ranges => {
8453
      return bind$3(ranges, range => {
8454
        const node = getSelectedNode(range);
8455
        return node ? [SugarElement.fromDom(node)] : [];
8456
      });
8457
    };
8458
    const hasMultipleRanges = selection => {
8459
      return getRanges$1(selection).length > 1;
8460
    };
8461
 
8462
    const getCellsFromRanges = ranges => filter$5(getSelectedNodes(ranges), isTableCell$2);
8463
    const getCellsFromElement = elm => descendants(elm, 'td[data-mce-selected],th[data-mce-selected]');
8464
    const getCellsFromElementOrRanges = (ranges, element) => {
8465
      const selectedCells = getCellsFromElement(element);
8466
      return selectedCells.length > 0 ? selectedCells : getCellsFromRanges(ranges);
8467
    };
8468
    const getCellsFromEditor = editor => getCellsFromElementOrRanges(getRanges$1(editor.selection.getSel()), SugarElement.fromDom(editor.getBody()));
8469
    const getClosestTable = (cell, isRoot) => ancestor$3(cell, 'table', isRoot);
8470
 
8471
    const getStartNode = rng => {
8472
      const sc = rng.startContainer, so = rng.startOffset;
8473
      if (isText$a(sc)) {
8474
        return so === 0 ? Optional.some(SugarElement.fromDom(sc)) : Optional.none();
8475
      } else {
8476
        return Optional.from(sc.childNodes[so]).map(SugarElement.fromDom);
8477
      }
8478
    };
8479
    const getEndNode = rng => {
8480
      const ec = rng.endContainer, eo = rng.endOffset;
8481
      if (isText$a(ec)) {
8482
        return eo === ec.data.length ? Optional.some(SugarElement.fromDom(ec)) : Optional.none();
8483
      } else {
8484
        return Optional.from(ec.childNodes[eo - 1]).map(SugarElement.fromDom);
8485
      }
8486
    };
8487
    const getFirstChildren = node => {
8488
      return firstChild(node).fold(constant([node]), child => {
8489
        return [node].concat(getFirstChildren(child));
8490
      });
8491
    };
8492
    const getLastChildren = node => {
8493
      return lastChild(node).fold(constant([node]), child => {
8494
        if (name(child) === 'br') {
8495
          return prevSibling(child).map(sibling => {
8496
            return [node].concat(getLastChildren(sibling));
8497
          }).getOr([]);
8498
        } else {
8499
          return [node].concat(getLastChildren(child));
8500
        }
8501
      });
8502
    };
8503
    const hasAllContentsSelected = (elm, rng) => {
8504
      return lift2(getStartNode(rng), getEndNode(rng), (startNode, endNode) => {
8505
        const start = find$2(getFirstChildren(elm), curry(eq, startNode));
8506
        const end = find$2(getLastChildren(elm), curry(eq, endNode));
8507
        return start.isSome() && end.isSome();
8508
      }).getOr(false);
8509
    };
8510
    const moveEndPoint = (dom, rng, node, start) => {
8511
      const root = node;
8512
      const walker = new DomTreeWalker(node, root);
8513
      const moveCaretBeforeOnEnterElementsMap = filter$4(dom.schema.getMoveCaretBeforeOnEnterElements(), (_, name) => !contains$2([
8514
        'td',
8515
        'th',
8516
        'table'
8517
      ], name.toLowerCase()));
8518
      let currentNode = node;
8519
      do {
8520
        if (isText$a(currentNode) && Tools.trim(currentNode.data).length !== 0) {
8521
          if (start) {
8522
            rng.setStart(currentNode, 0);
8523
          } else {
8524
            rng.setEnd(currentNode, currentNode.data.length);
8525
          }
8526
          return;
8527
        }
8528
        if (moveCaretBeforeOnEnterElementsMap[currentNode.nodeName]) {
8529
          if (start) {
8530
            rng.setStartBefore(currentNode);
8531
          } else {
8532
            if (currentNode.nodeName === 'BR') {
8533
              rng.setEndBefore(currentNode);
8534
            } else {
8535
              rng.setEndAfter(currentNode);
8536
            }
8537
          }
8538
          return;
8539
        }
8540
      } while (currentNode = start ? walker.next() : walker.prev());
8541
      if (root.nodeName === 'BODY') {
8542
        if (start) {
8543
          rng.setStart(root, 0);
8544
        } else {
8545
          rng.setEnd(root, root.childNodes.length);
8546
        }
8547
      }
8548
    };
8549
    const hasAnyRanges = editor => {
8550
      const sel = editor.selection.getSel();
8551
      return isNonNullable(sel) && sel.rangeCount > 0;
8552
    };
8553
    const runOnRanges = (editor, executor) => {
8554
      const fakeSelectionNodes = getCellsFromEditor(editor);
8555
      if (fakeSelectionNodes.length > 0) {
8556
        each$e(fakeSelectionNodes, elem => {
8557
          const node = elem.dom;
8558
          const fakeNodeRng = editor.dom.createRng();
8559
          fakeNodeRng.setStartBefore(node);
8560
          fakeNodeRng.setEndAfter(node);
8561
          executor(fakeNodeRng, true);
8562
        });
8563
      } else {
8564
        executor(editor.selection.getRng(), false);
8565
      }
8566
    };
8567
    const preserve = (selection, fillBookmark, executor) => {
8568
      const bookmark = getPersistentBookmark(selection, fillBookmark);
8569
      executor(bookmark);
8570
      selection.moveToBookmark(bookmark);
8571
    };
8572
 
8573
    const isNode = node => isNumber(node === null || node === void 0 ? void 0 : node.nodeType);
8574
    const isElementNode$1 = node => isElement$6(node) && !isBookmarkNode$1(node) && !isCaretNode(node) && !isBogus$2(node);
8575
    const isElementDirectlySelected = (dom, node) => {
8576
      if (isElementNode$1(node) && !/^(TD|TH)$/.test(node.nodeName)) {
8577
        const selectedAttr = dom.getAttrib(node, 'data-mce-selected');
8578
        const value = parseInt(selectedAttr, 10);
8579
        return !isNaN(value) && value > 0;
8580
      } else {
8581
        return false;
8582
      }
8583
    };
8584
    const preserveSelection = (editor, action, shouldMoveStart) => {
8585
      const {selection, dom} = editor;
8586
      const selectedNodeBeforeAction = selection.getNode();
8587
      const isSelectedBeforeNodeNoneditable = isContentEditableFalse$b(selectedNodeBeforeAction);
8588
      preserve(selection, true, () => {
8589
        action();
8590
      });
8591
      const isBeforeNodeStillNoneditable = isSelectedBeforeNodeNoneditable && isContentEditableFalse$b(selectedNodeBeforeAction);
8592
      if (isBeforeNodeStillNoneditable && dom.isChildOf(selectedNodeBeforeAction, editor.getBody())) {
8593
        editor.selection.select(selectedNodeBeforeAction);
8594
      } else if (shouldMoveStart(selection.getStart())) {
8595
        moveStartToNearestText(dom, selection);
8596
      }
8597
    };
8598
    const moveStartToNearestText = (dom, selection) => {
8599
      var _a, _b;
8600
      const rng = selection.getRng();
8601
      const {startContainer, startOffset} = rng;
8602
      const selectedNode = selection.getNode();
8603
      if (isElementDirectlySelected(dom, selectedNode)) {
8604
        return;
8605
      }
8606
      if (isElement$6(startContainer)) {
8607
        const nodes = startContainer.childNodes;
8608
        const root = dom.getRoot();
8609
        let walker;
8610
        if (startOffset < nodes.length) {
8611
          const startNode = nodes[startOffset];
8612
          walker = new DomTreeWalker(startNode, (_a = dom.getParent(startNode, dom.isBlock)) !== null && _a !== void 0 ? _a : root);
8613
        } else {
8614
          const startNode = nodes[nodes.length - 1];
8615
          walker = new DomTreeWalker(startNode, (_b = dom.getParent(startNode, dom.isBlock)) !== null && _b !== void 0 ? _b : root);
8616
          walker.next(true);
8617
        }
8618
        for (let node = walker.current(); node; node = walker.next()) {
8619
          if (dom.getContentEditable(node) === 'false') {
8620
            return;
8621
          } else if (isText$a(node) && !isWhiteSpaceNode$1(node)) {
8622
            rng.setStart(node, 0);
8623
            selection.setRng(rng);
8624
            return;
8625
          }
8626
        }
8627
      }
8628
    };
8629
    const getNonWhiteSpaceSibling = (node, next, inc) => {
8630
      if (node) {
8631
        const nextName = next ? 'nextSibling' : 'previousSibling';
8632
        for (node = inc ? node : node[nextName]; node; node = node[nextName]) {
8633
          if (isElement$6(node) || !isWhiteSpaceNode$1(node)) {
8634
            return node;
8635
          }
8636
        }
8637
      }
8638
      return undefined;
8639
    };
8640
    const isTextBlock$1 = (schema, node) => !!schema.getTextBlockElements()[node.nodeName.toLowerCase()] || isTransparentBlock(schema, node);
8641
    const isValid = (ed, parent, child) => {
8642
      return ed.schema.isValidChild(parent, child);
8643
    };
8644
    const isWhiteSpaceNode$1 = (node, allowSpaces = false) => {
8645
      if (isNonNullable(node) && isText$a(node)) {
8646
        const data = allowSpaces ? node.data.replace(/ /g, '\xA0') : node.data;
8647
        return isWhitespaceText(data);
8648
      } else {
8649
        return false;
8650
      }
8651
    };
8652
    const isEmptyTextNode$1 = node => {
8653
      return isNonNullable(node) && isText$a(node) && node.length === 0;
8654
    };
8655
    const isWrapNoneditableTarget = (editor, node) => {
8656
      const baseDataSelector = '[data-mce-cef-wrappable]';
8657
      const formatNoneditableSelector = getFormatNoneditableSelector(editor);
8658
      const selector = isEmpty$3(formatNoneditableSelector) ? baseDataSelector : `${ baseDataSelector },${ formatNoneditableSelector }`;
8659
      return is$1(SugarElement.fromDom(node), selector);
8660
    };
8661
    const isWrappableNoneditable = (editor, node) => {
8662
      const dom = editor.dom;
8663
      return isElementNode$1(node) && dom.getContentEditable(node) === 'false' && isWrapNoneditableTarget(editor, node) && dom.select('[contenteditable="true"]', node).length === 0;
8664
    };
8665
    const replaceVars = (value, vars) => {
8666
      if (isFunction(value)) {
8667
        return value(vars);
8668
      } else if (isNonNullable(vars)) {
8669
        value = value.replace(/%(\w+)/g, (str, name) => {
8670
          return vars[name] || str;
8671
        });
8672
      }
8673
      return value;
8674
    };
8675
    const isEq$5 = (str1, str2) => {
8676
      str1 = str1 || '';
8677
      str2 = str2 || '';
8678
      str1 = '' + (str1.nodeName || str1);
8679
      str2 = '' + (str2.nodeName || str2);
8680
      return str1.toLowerCase() === str2.toLowerCase();
8681
    };
8682
    const normalizeStyleValue = (value, name) => {
8683
      if (isNullable(value)) {
8684
        return null;
8685
      } else {
8686
        let strValue = String(value);
8687
        if (name === 'color' || name === 'backgroundColor') {
8688
          strValue = rgbaToHexString(strValue);
8689
        }
8690
        if (name === 'fontWeight' && value === 700) {
8691
          strValue = 'bold';
8692
        }
8693
        if (name === 'fontFamily') {
8694
          strValue = strValue.replace(/[\'\"]/g, '').replace(/,\s+/g, ',');
8695
        }
8696
        return strValue;
8697
      }
8698
    };
8699
    const getStyle = (dom, node, name) => {
8700
      const style = dom.getStyle(node, name);
8701
      return normalizeStyleValue(style, name);
8702
    };
8703
    const getTextDecoration = (dom, node) => {
8704
      let decoration;
8705
      dom.getParent(node, n => {
8706
        if (isElement$6(n)) {
8707
          decoration = dom.getStyle(n, 'text-decoration');
8708
          return !!decoration && decoration !== 'none';
8709
        } else {
8710
          return false;
8711
        }
8712
      });
8713
      return decoration;
8714
    };
8715
    const getParents$2 = (dom, node, selector) => {
8716
      return dom.getParents(node, selector, dom.getRoot());
8717
    };
8718
    const isFormatPredicate = (editor, formatName, predicate) => {
8719
      const formats = editor.formatter.get(formatName);
8720
      return isNonNullable(formats) && exists(formats, predicate);
8721
    };
8722
    const isVariableFormatName = (editor, formatName) => {
8723
      const hasVariableValues = format => {
8724
        const isVariableValue = val => isFunction(val) || val.length > 1 && val.charAt(0) === '%';
8725
        return exists([
8726
          'styles',
8727
          'attributes'
8728
        ], key => get$a(format, key).exists(field => {
8729
          const fieldValues = isArray$1(field) ? field : values(field);
8730
          return exists(fieldValues, isVariableValue);
8731
        }));
8732
      };
8733
      return isFormatPredicate(editor, formatName, hasVariableValues);
8734
    };
8735
    const areSimilarFormats = (editor, formatName, otherFormatName) => {
8736
      const validKeys = [
8737
        'inline',
8738
        'block',
8739
        'selector',
8740
        'attributes',
8741
        'styles',
8742
        'classes'
8743
      ];
8744
      const filterObj = format => filter$4(format, (_, key) => exists(validKeys, validKey => validKey === key));
8745
      return isFormatPredicate(editor, formatName, fmt1 => {
8746
        const filteredFmt1 = filterObj(fmt1);
8747
        return isFormatPredicate(editor, otherFormatName, fmt2 => {
8748
          const filteredFmt2 = filterObj(fmt2);
8749
          return equal$1(filteredFmt1, filteredFmt2);
8750
        });
8751
      });
8752
    };
8753
    const isBlockFormat = format => hasNonNullableKey(format, 'block');
8754
    const isWrappingBlockFormat = format => isBlockFormat(format) && format.wrapper === true;
8755
    const isNonWrappingBlockFormat = format => isBlockFormat(format) && format.wrapper !== true;
8756
    const isSelectorFormat = format => hasNonNullableKey(format, 'selector');
8757
    const isInlineFormat = format => hasNonNullableKey(format, 'inline');
8758
    const isMixedFormat = format => isSelectorFormat(format) && isInlineFormat(format) && is$2(get$a(format, 'mixed'), true);
8759
    const shouldExpandToSelector = format => isSelectorFormat(format) && format.expand !== false && !isInlineFormat(format);
8760
    const getEmptyCaretContainers = node => {
8761
      const nodes = [];
8762
      let tempNode = node;
8763
      while (tempNode) {
8764
        if (isText$a(tempNode) && tempNode.data !== ZWSP$1 || tempNode.childNodes.length > 1) {
8765
          return [];
8766
        }
8767
        if (isElement$6(tempNode)) {
8768
          nodes.push(tempNode);
8769
        }
8770
        tempNode = tempNode.firstChild;
8771
      }
8772
      return nodes;
8773
    };
8774
    const isCaretContainerEmpty = node => {
8775
      return getEmptyCaretContainers(node).length > 0;
8776
    };
8777
    const isEmptyCaretFormatElement = element => {
8778
      return isCaretNode(element.dom) && isCaretContainerEmpty(element.dom);
8779
    };
8780
 
8781
    const isBookmarkNode = isBookmarkNode$1;
8782
    const getParents$1 = getParents$2;
8783
    const isWhiteSpaceNode = isWhiteSpaceNode$1;
8784
    const isTextBlock = isTextBlock$1;
8785
    const isBogusBr = node => {
8786
      return isBr$6(node) && node.getAttribute('data-mce-bogus') && !node.nextSibling;
8787
    };
8788
    const findParentContentEditable = (dom, node) => {
8789
      let parent = node;
8790
      while (parent) {
8791
        if (isElement$6(parent) && dom.getContentEditable(parent)) {
8792
          return dom.getContentEditable(parent) === 'false' ? parent : node;
8793
        }
8794
        parent = parent.parentNode;
8795
      }
8796
      return node;
8797
    };
8798
    const walkText = (start, node, offset, predicate) => {
8799
      const str = node.data;
8800
      if (start) {
8801
        for (let i = offset; i > 0; i--) {
8802
          if (predicate(str.charAt(i - 1))) {
8803
            return i;
8804
          }
8805
        }
8806
      } else {
8807
        for (let i = offset; i < str.length; i++) {
8808
          if (predicate(str.charAt(i))) {
8809
            return i;
8810
          }
8811
        }
8812
      }
8813
      return -1;
8814
    };
8815
    const findSpace = (start, node, offset) => walkText(start, node, offset, c => isNbsp(c) || isWhiteSpace(c));
8816
    const findContent = (start, node, offset) => walkText(start, node, offset, isContent);
8817
    const findWordEndPoint = (dom, body, container, offset, start, includeTrailingSpaces) => {
8818
      let lastTextNode;
8819
      const rootNode = dom.getParent(container, dom.isBlock) || body;
8820
      const walk = (container, offset, pred) => {
8821
        const textSeeker = TextSeeker(dom);
8822
        const walker = start ? textSeeker.backwards : textSeeker.forwards;
8823
        return Optional.from(walker(container, offset, (text, textOffset) => {
8824
          if (isBookmarkNode(text.parentNode)) {
8825
            return -1;
8826
          } else {
8827
            lastTextNode = text;
8828
            return pred(start, text, textOffset);
8829
          }
8830
        }, rootNode));
8831
      };
8832
      const spaceResult = walk(container, offset, findSpace);
8833
      return spaceResult.bind(result => includeTrailingSpaces ? walk(result.container, result.offset + (start ? -1 : 0), findContent) : Optional.some(result)).orThunk(() => lastTextNode ? Optional.some({
8834
        container: lastTextNode,
8835
        offset: start ? 0 : lastTextNode.length
8836
      }) : Optional.none());
8837
    };
8838
    const findSelectorEndPoint = (dom, formatList, rng, container, siblingName) => {
8839
      const sibling = container[siblingName];
8840
      if (isText$a(container) && isEmpty$3(container.data) && sibling) {
8841
        container = sibling;
8842
      }
8843
      const parents = getParents$1(dom, container);
8844
      for (let i = 0; i < parents.length; i++) {
8845
        for (let y = 0; y < formatList.length; y++) {
8846
          const curFormat = formatList[y];
8847
          if (isNonNullable(curFormat.collapsed) && curFormat.collapsed !== rng.collapsed) {
8848
            continue;
8849
          }
8850
          if (isSelectorFormat(curFormat) && dom.is(parents[i], curFormat.selector)) {
8851
            return parents[i];
8852
          }
8853
        }
8854
      }
8855
      return container;
8856
    };
8857
    const findBlockEndPoint = (dom, formatList, container, siblingName) => {
8858
      var _a;
8859
      let node = container;
8860
      const root = dom.getRoot();
8861
      const format = formatList[0];
8862
      if (isBlockFormat(format)) {
8863
        node = format.wrapper ? null : dom.getParent(container, format.block, root);
8864
      }
8865
      if (!node) {
8866
        const scopeRoot = (_a = dom.getParent(container, 'LI,TD,TH,SUMMARY')) !== null && _a !== void 0 ? _a : root;
8867
        node = dom.getParent(isText$a(container) ? container.parentNode : container, node => node !== root && isTextBlock(dom.schema, node), scopeRoot);
8868
      }
8869
      if (node && isBlockFormat(format) && format.wrapper) {
8870
        node = getParents$1(dom, node, 'ul,ol').reverse()[0] || node;
8871
      }
8872
      if (!node) {
8873
        node = container;
8874
        while (node && node[siblingName] && !dom.isBlock(node[siblingName])) {
8875
          node = node[siblingName];
8876
          if (isEq$5(node, 'br')) {
8877
            break;
8878
          }
8879
        }
8880
      }
8881
      return node || container;
8882
    };
8883
    const isAtBlockBoundary$1 = (dom, root, container, siblingName) => {
8884
      const parent = container.parentNode;
8885
      if (isNonNullable(container[siblingName])) {
8886
        return false;
8887
      } else if (parent === root || isNullable(parent) || dom.isBlock(parent)) {
8888
        return true;
8889
      } else {
8890
        return isAtBlockBoundary$1(dom, root, parent, siblingName);
8891
      }
8892
    };
8893
    const findParentContainer = (dom, formatList, container, offset, start) => {
8894
      let parent = container;
8895
      const siblingName = start ? 'previousSibling' : 'nextSibling';
8896
      const root = dom.getRoot();
8897
      if (isText$a(container) && !isWhiteSpaceNode(container)) {
8898
        if (start ? offset > 0 : offset < container.data.length) {
8899
          return container;
8900
        }
8901
      }
8902
      while (parent) {
8903
        if (!formatList[0].block_expand && dom.isBlock(parent)) {
8904
          return parent;
8905
        }
8906
        for (let sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {
8907
          const allowSpaces = isText$a(sibling) && !isAtBlockBoundary$1(dom, root, sibling, siblingName);
8908
          if (!isBookmarkNode(sibling) && !isBogusBr(sibling) && !isWhiteSpaceNode(sibling, allowSpaces)) {
8909
            return parent;
8910
          }
8911
        }
8912
        if (parent === root || parent.parentNode === root) {
8913
          container = parent;
8914
          break;
8915
        }
8916
        parent = parent.parentNode;
8917
      }
8918
      return container;
8919
    };
8920
    const isSelfOrParentBookmark = container => isBookmarkNode(container.parentNode) || isBookmarkNode(container);
8921
    const expandRng = (dom, rng, formatList, includeTrailingSpace = false) => {
8922
      let {startContainer, startOffset, endContainer, endOffset} = rng;
8923
      const format = formatList[0];
8924
      if (isElement$6(startContainer) && startContainer.hasChildNodes()) {
8925
        startContainer = getNode$1(startContainer, startOffset);
8926
        if (isText$a(startContainer)) {
8927
          startOffset = 0;
8928
        }
8929
      }
8930
      if (isElement$6(endContainer) && endContainer.hasChildNodes()) {
8931
        endContainer = getNode$1(endContainer, rng.collapsed ? endOffset : endOffset - 1);
8932
        if (isText$a(endContainer)) {
8933
          endOffset = endContainer.data.length;
8934
        }
8935
      }
8936
      startContainer = findParentContentEditable(dom, startContainer);
8937
      endContainer = findParentContentEditable(dom, endContainer);
8938
      if (isSelfOrParentBookmark(startContainer)) {
8939
        startContainer = isBookmarkNode(startContainer) ? startContainer : startContainer.parentNode;
8940
        if (rng.collapsed) {
8941
          startContainer = startContainer.previousSibling || startContainer;
8942
        } else {
8943
          startContainer = startContainer.nextSibling || startContainer;
8944
        }
8945
        if (isText$a(startContainer)) {
8946
          startOffset = rng.collapsed ? startContainer.length : 0;
8947
        }
8948
      }
8949
      if (isSelfOrParentBookmark(endContainer)) {
8950
        endContainer = isBookmarkNode(endContainer) ? endContainer : endContainer.parentNode;
8951
        if (rng.collapsed) {
8952
          endContainer = endContainer.nextSibling || endContainer;
8953
        } else {
8954
          endContainer = endContainer.previousSibling || endContainer;
8955
        }
8956
        if (isText$a(endContainer)) {
8957
          endOffset = rng.collapsed ? 0 : endContainer.length;
8958
        }
8959
      }
8960
      if (rng.collapsed) {
8961
        const startPoint = findWordEndPoint(dom, dom.getRoot(), startContainer, startOffset, true, includeTrailingSpace);
8962
        startPoint.each(({container, offset}) => {
8963
          startContainer = container;
8964
          startOffset = offset;
8965
        });
8966
        const endPoint = findWordEndPoint(dom, dom.getRoot(), endContainer, endOffset, false, includeTrailingSpace);
8967
        endPoint.each(({container, offset}) => {
8968
          endContainer = container;
8969
          endOffset = offset;
8970
        });
8971
      }
8972
      if (isInlineFormat(format) || format.block_expand) {
8973
        if (!isInlineFormat(format) || (!isText$a(startContainer) || startOffset === 0)) {
8974
          startContainer = findParentContainer(dom, formatList, startContainer, startOffset, true);
8975
        }
8976
        if (!isInlineFormat(format) || (!isText$a(endContainer) || endOffset === endContainer.data.length)) {
8977
          endContainer = findParentContainer(dom, formatList, endContainer, endOffset, false);
8978
        }
8979
      }
8980
      if (shouldExpandToSelector(format)) {
8981
        startContainer = findSelectorEndPoint(dom, formatList, rng, startContainer, 'previousSibling');
8982
        endContainer = findSelectorEndPoint(dom, formatList, rng, endContainer, 'nextSibling');
8983
      }
8984
      if (isBlockFormat(format) || isSelectorFormat(format)) {
8985
        startContainer = findBlockEndPoint(dom, formatList, startContainer, 'previousSibling');
8986
        endContainer = findBlockEndPoint(dom, formatList, endContainer, 'nextSibling');
8987
        if (isBlockFormat(format)) {
8988
          if (!dom.isBlock(startContainer)) {
8989
            startContainer = findParentContainer(dom, formatList, startContainer, startOffset, true);
8990
          }
8991
          if (!dom.isBlock(endContainer)) {
8992
            endContainer = findParentContainer(dom, formatList, endContainer, endOffset, false);
8993
          }
8994
        }
8995
      }
8996
      if (isElement$6(startContainer) && startContainer.parentNode) {
8997
        startOffset = dom.nodeIndex(startContainer);
8998
        startContainer = startContainer.parentNode;
8999
      }
9000
      if (isElement$6(endContainer) && endContainer.parentNode) {
9001
        endOffset = dom.nodeIndex(endContainer) + 1;
9002
        endContainer = endContainer.parentNode;
9003
      }
9004
      return {
9005
        startContainer,
9006
        startOffset,
9007
        endContainer,
9008
        endOffset
9009
      };
9010
    };
9011
 
9012
    const walk$3 = (dom, rng, callback) => {
9013
      var _a;
9014
      const startOffset = rng.startOffset;
9015
      const startContainer = getNode$1(rng.startContainer, startOffset);
9016
      const endOffset = rng.endOffset;
9017
      const endContainer = getNode$1(rng.endContainer, endOffset - 1);
9018
      const exclude = nodes => {
9019
        const firstNode = nodes[0];
9020
        if (isText$a(firstNode) && firstNode === startContainer && startOffset >= firstNode.data.length) {
9021
          nodes.splice(0, 1);
9022
        }
9023
        const lastNode = nodes[nodes.length - 1];
9024
        if (endOffset === 0 && nodes.length > 0 && lastNode === endContainer && isText$a(lastNode)) {
9025
          nodes.splice(nodes.length - 1, 1);
9026
        }
9027
        return nodes;
9028
      };
9029
      const collectSiblings = (node, name, endNode) => {
9030
        const siblings = [];
9031
        for (; node && node !== endNode; node = node[name]) {
9032
          siblings.push(node);
9033
        }
9034
        return siblings;
9035
      };
9036
      const findEndPoint = (node, root) => dom.getParent(node, node => node.parentNode === root, root);
9037
      const walkBoundary = (startNode, endNode, next) => {
9038
        const siblingName = next ? 'nextSibling' : 'previousSibling';
9039
        for (let node = startNode, parent = node.parentNode; node && node !== endNode; node = parent) {
9040
          parent = node.parentNode;
9041
          const siblings = collectSiblings(node === startNode ? node : node[siblingName], siblingName);
9042
          if (siblings.length) {
9043
            if (!next) {
9044
              siblings.reverse();
9045
            }
9046
            callback(exclude(siblings));
9047
          }
9048
        }
9049
      };
9050
      if (startContainer === endContainer) {
9051
        return callback(exclude([startContainer]));
9052
      }
9053
      const ancestor = (_a = dom.findCommonAncestor(startContainer, endContainer)) !== null && _a !== void 0 ? _a : dom.getRoot();
9054
      if (dom.isChildOf(startContainer, endContainer)) {
9055
        return walkBoundary(startContainer, ancestor, true);
9056
      }
9057
      if (dom.isChildOf(endContainer, startContainer)) {
9058
        return walkBoundary(endContainer, ancestor);
9059
      }
9060
      const startPoint = findEndPoint(startContainer, ancestor) || startContainer;
9061
      const endPoint = findEndPoint(endContainer, ancestor) || endContainer;
9062
      walkBoundary(startContainer, startPoint, true);
9063
      const siblings = collectSiblings(startPoint === startContainer ? startPoint : startPoint.nextSibling, 'nextSibling', endPoint === endContainer ? endPoint.nextSibling : endPoint);
9064
      if (siblings.length) {
9065
        callback(exclude(siblings));
9066
      }
9067
      walkBoundary(endContainer, endPoint);
9068
    };
9069
 
9070
    const validBlocks = [
9071
      'pre[class*=language-][contenteditable="false"]',
9072
      'figure.image',
9073
      'div[data-ephox-embed-iri]',
9074
      'div.tiny-pageembed',
9075
      'div.mce-toc',
9076
      'div[data-mce-toc]'
9077
    ];
9078
    const isZeroWidth = elem => isText$b(elem) && get$3(elem) === ZWSP$1;
9079
    const context = (editor, elem, wrapName, nodeName) => parent(elem).fold(() => 'skipping', parent => {
9080
      if (nodeName === 'br' || isZeroWidth(elem)) {
9081
        return 'valid';
9082
      } else if (isAnnotation(elem)) {
9083
        return 'existing';
9084
      } else if (isCaretNode(elem.dom)) {
9085
        return 'caret';
9086
      } else if (exists(validBlocks, selector => is$1(elem, selector))) {
9087
        return 'valid-block';
9088
      } else if (!isValid(editor, wrapName, nodeName) || !isValid(editor, name(parent), wrapName)) {
9089
        return 'invalid-child';
9090
      } else {
9091
        return 'valid';
9092
      }
9093
    });
9094
 
9095
    const applyWordGrab = (editor, rng) => {
9096
      const r = expandRng(editor.dom, rng, [{ inline: 'span' }]);
9097
      rng.setStart(r.startContainer, r.startOffset);
9098
      rng.setEnd(r.endContainer, r.endOffset);
9099
      editor.selection.setRng(rng);
9100
    };
9101
    const applyAnnotation = (elem, masterUId, data, annotationName, decorate, directAnnotation) => {
9102
      const {uid = masterUId, ...otherData} = data;
9103
      add$2(elem, annotation());
9104
      set$3(elem, `${ dataAnnotationId() }`, uid);
9105
      set$3(elem, `${ dataAnnotation() }`, annotationName);
9106
      const {attributes = {}, classes = []} = decorate(uid, otherData);
9107
      setAll$1(elem, attributes);
9108
      add(elem, classes);
9109
      if (directAnnotation) {
9110
        if (classes.length > 0) {
9111
          set$3(elem, `${ dataAnnotationClasses() }`, classes.join(','));
9112
        }
9113
        const attributeNames = keys(attributes);
9114
        if (attributeNames.length > 0) {
9115
          set$3(elem, `${ dataAnnotationAttributes() }`, attributeNames.join(','));
9116
        }
9117
      }
9118
    };
9119
    const removeDirectAnnotation = elem => {
9120
      remove$7(elem, annotation());
9121
      remove$a(elem, `${ dataAnnotationId() }`);
9122
      remove$a(elem, `${ dataAnnotation() }`);
9123
      remove$a(elem, `${ dataAnnotationActive() }`);
9124
      const customAttrNames = getOpt(elem, `${ dataAnnotationAttributes() }`).map(names => names.split(',')).getOr([]);
9125
      const customClasses = getOpt(elem, `${ dataAnnotationClasses() }`).map(names => names.split(',')).getOr([]);
9126
      each$e(customAttrNames, name => remove$a(elem, name));
9127
      remove$4(elem, customClasses);
9128
      remove$a(elem, `${ dataAnnotationClasses() }`);
9129
      remove$a(elem, `${ dataAnnotationAttributes() }`);
9130
    };
9131
    const makeAnnotation = (eDoc, uid, data, annotationName, decorate) => {
9132
      const master = SugarElement.fromTag('span', eDoc);
9133
      applyAnnotation(master, uid, data, annotationName, decorate, false);
9134
      return master;
9135
    };
9136
    const annotate = (editor, rng, uid, annotationName, decorate, data) => {
9137
      const newWrappers = [];
9138
      const master = makeAnnotation(editor.getDoc(), uid, data, annotationName, decorate);
9139
      const wrapper = value$2();
9140
      const finishWrapper = () => {
9141
        wrapper.clear();
9142
      };
9143
      const getOrOpenWrapper = () => wrapper.get().getOrThunk(() => {
9144
        const nu = shallow$1(master);
9145
        newWrappers.push(nu);
9146
        wrapper.set(nu);
9147
        return nu;
9148
      });
9149
      const processElements = elems => {
9150
        each$e(elems, processElement);
9151
      };
9152
      const processElement = elem => {
9153
        const ctx = context(editor, elem, 'span', name(elem));
9154
        switch (ctx) {
9155
        case 'invalid-child': {
9156
            finishWrapper();
9157
            const children = children$1(elem);
9158
            processElements(children);
9159
            finishWrapper();
9160
            break;
9161
          }
9162
        case 'valid-block': {
9163
            finishWrapper();
9164
            applyAnnotation(elem, uid, data, annotationName, decorate, true);
9165
            break;
9166
          }
9167
        case 'valid': {
9168
            const w = getOrOpenWrapper();
9169
            wrap$2(elem, w);
9170
            break;
9171
          }
9172
        }
9173
      };
9174
      const processNodes = nodes => {
9175
        const elems = map$3(nodes, SugarElement.fromDom);
9176
        processElements(elems);
9177
      };
9178
      walk$3(editor.dom, rng, nodes => {
9179
        finishWrapper();
9180
        processNodes(nodes);
9181
      });
9182
      return newWrappers;
9183
    };
9184
    const annotateWithBookmark = (editor, name, settings, data) => {
9185
      editor.undoManager.transact(() => {
9186
        const selection = editor.selection;
9187
        const initialRng = selection.getRng();
9188
        const hasFakeSelection = getCellsFromEditor(editor).length > 0;
9189
        const masterUid = generate$1('mce-annotation');
9190
        if (initialRng.collapsed && !hasFakeSelection) {
9191
          applyWordGrab(editor, initialRng);
9192
        }
9193
        if (selection.getRng().collapsed && !hasFakeSelection) {
9194
          const wrapper = makeAnnotation(editor.getDoc(), masterUid, data, name, settings.decorate);
9195
          set$1(wrapper, nbsp);
9196
          selection.getRng().insertNode(wrapper.dom);
9197
          selection.select(wrapper.dom);
9198
        } else {
9199
          preserve(selection, false, () => {
9200
            runOnRanges(editor, selectionRng => {
9201
              annotate(editor, selectionRng, masterUid, name, settings.decorate, data);
9202
            });
9203
          });
9204
        }
9205
      });
9206
    };
9207
 
9208
    const Annotator = editor => {
9209
      const registry = create$c();
9210
      setup$x(editor, registry);
9211
      const changes = setup$y(editor, registry);
9212
      const isSpan = isTag('span');
9213
      const removeAnnotations = elements => {
9214
        each$e(elements, element => {
9215
          if (isSpan(element)) {
9216
            unwrap(element);
9217
          } else {
9218
            removeDirectAnnotation(element);
9219
          }
9220
        });
9221
      };
9222
      return {
9223
        register: (name, settings) => {
9224
          registry.register(name, settings);
9225
        },
9226
        annotate: (name, data) => {
9227
          registry.lookup(name).each(settings => {
9228
            annotateWithBookmark(editor, name, settings, data);
9229
          });
9230
        },
9231
        annotationChanged: (name, callback) => {
9232
          changes.addListener(name, callback);
9233
        },
9234
        remove: name => {
9235
          identify(editor, Optional.some(name)).each(({elements}) => {
9236
            const bookmark = editor.selection.getBookmark();
9237
            removeAnnotations(elements);
9238
            editor.selection.moveToBookmark(bookmark);
9239
          });
9240
        },
9241
        removeAll: name => {
9242
          const bookmark = editor.selection.getBookmark();
9243
          each$d(findAll(editor, name), (elements, _) => {
9244
            removeAnnotations(elements);
9245
          });
9246
          editor.selection.moveToBookmark(bookmark);
9247
        },
9248
        getAll: name => {
9249
          const directory = findAll(editor, name);
9250
          return map$2(directory, elems => map$3(elems, elem => elem.dom));
9251
        }
9252
      };
9253
    };
9254
 
9255
    const BookmarkManager = selection => {
9256
      return {
9257
        getBookmark: curry(getBookmark$1, selection),
9258
        moveToBookmark: curry(moveToBookmark, selection)
9259
      };
9260
    };
9261
    BookmarkManager.isBookmarkNode = isBookmarkNode$1;
9262
 
9263
    const isXYWithinRange = (clientX, clientY, range) => {
9264
      if (range.collapsed) {
9265
        return false;
9266
      } else {
9267
        return exists(range.getClientRects(), rect => containsXY(rect, clientX, clientY));
9268
      }
9269
    };
9270
 
9271
    const firePreProcess = (editor, args) => editor.dispatch('PreProcess', args);
9272
    const firePostProcess = (editor, args) => editor.dispatch('PostProcess', args);
9273
    const fireRemove = editor => {
9274
      editor.dispatch('remove');
9275
    };
9276
    const fireDetach = editor => {
9277
      editor.dispatch('detach');
9278
    };
9279
    const fireSwitchMode = (editor, mode) => {
9280
      editor.dispatch('SwitchMode', { mode });
9281
    };
9282
    const fireObjectResizeStart = (editor, target, width, height, origin) => {
9283
      editor.dispatch('ObjectResizeStart', {
9284
        target,
9285
        width,
9286
        height,
9287
        origin
9288
      });
9289
    };
9290
    const fireObjectResized = (editor, target, width, height, origin) => {
9291
      editor.dispatch('ObjectResized', {
9292
        target,
9293
        width,
9294
        height,
9295
        origin
9296
      });
9297
    };
9298
    const firePreInit = editor => {
9299
      editor.dispatch('PreInit');
9300
    };
9301
    const firePostRender = editor => {
9302
      editor.dispatch('PostRender');
9303
    };
9304
    const fireInit = editor => {
9305
      editor.dispatch('Init');
9306
    };
9307
    const firePlaceholderToggle = (editor, state) => {
9308
      editor.dispatch('PlaceholderToggle', { state });
9309
    };
9310
    const fireError = (editor, errorType, error) => {
9311
      editor.dispatch(errorType, error);
9312
    };
9313
    const fireFormatApply = (editor, format, node, vars) => {
9314
      editor.dispatch('FormatApply', {
9315
        format,
9316
        node,
9317
        vars
9318
      });
9319
    };
9320
    const fireFormatRemove = (editor, format, node, vars) => {
9321
      editor.dispatch('FormatRemove', {
9322
        format,
9323
        node,
9324
        vars
9325
      });
9326
    };
9327
    const fireBeforeSetContent = (editor, args) => editor.dispatch('BeforeSetContent', args);
9328
    const fireSetContent = (editor, args) => editor.dispatch('SetContent', args);
9329
    const fireBeforeGetContent = (editor, args) => editor.dispatch('BeforeGetContent', args);
9330
    const fireGetContent = (editor, args) => editor.dispatch('GetContent', args);
9331
    const fireAutocompleterStart = (editor, args) => {
9332
      editor.dispatch('AutocompleterStart', args);
9333
    };
9334
    const fireAutocompleterUpdate = (editor, args) => {
9335
      editor.dispatch('AutocompleterUpdate', args);
9336
    };
9337
    const fireAutocompleterEnd = editor => {
9338
      editor.dispatch('AutocompleterEnd');
9339
    };
9340
    const firePastePreProcess = (editor, html, internal) => editor.dispatch('PastePreProcess', {
9341
      content: html,
9342
      internal
9343
    });
9344
    const firePastePostProcess = (editor, node, internal) => editor.dispatch('PastePostProcess', {
9345
      node,
9346
      internal
9347
    });
9348
    const firePastePlainTextToggle = (editor, state) => editor.dispatch('PastePlainTextToggle', { state });
9349
    const fireEditableRootStateChange = (editor, state) => editor.dispatch('EditableRootStateChange', { state });
9350
 
9351
    const VK = {
9352
      BACKSPACE: 8,
9353
      DELETE: 46,
9354
      DOWN: 40,
9355
      ENTER: 13,
9356
      ESC: 27,
9357
      LEFT: 37,
9358
      RIGHT: 39,
9359
      SPACEBAR: 32,
9360
      TAB: 9,
9361
      UP: 38,
9362
      PAGE_UP: 33,
9363
      PAGE_DOWN: 34,
9364
      END: 35,
9365
      HOME: 36,
9366
      modifierPressed: e => {
9367
        return e.shiftKey || e.ctrlKey || e.altKey || VK.metaKeyPressed(e);
9368
      },
9369
      metaKeyPressed: e => {
9370
        return Env.os.isMacOS() || Env.os.isiOS() ? e.metaKey : e.ctrlKey && !e.altKey;
9371
      }
9372
    };
9373
 
9374
    const elementSelectionAttr = 'data-mce-selected';
9375
    const controlElmSelector = 'table,img,figure.image,hr,video,span.mce-preview-object,details';
9376
    const abs = Math.abs;
9377
    const round$1 = Math.round;
9378
    const resizeHandles = {
9379
      nw: [
9380
        0,
9381
        0,
9382
        -1,
9383
        -1
9384
      ],
9385
      ne: [
9386
        1,
9387
        0,
9388
        1,
9389
        -1
9390
      ],
9391
      se: [
9392
        1,
9393
        1,
9394
        1,
9395
        1
9396
      ],
9397
      sw: [
9398
        0,
9399
        1,
9400
        -1,
9401
        1
9402
      ]
9403
    };
9404
    const isTouchEvent = evt => evt.type === 'longpress' || evt.type.indexOf('touch') === 0;
9405
    const ControlSelection = (selection, editor) => {
9406
      const dom = editor.dom;
9407
      const editableDoc = editor.getDoc();
9408
      const rootDocument = document;
9409
      const rootElement = editor.getBody();
9410
      let selectedElm, selectedElmGhost, resizeHelper, selectedHandle, resizeBackdrop;
9411
      let startX, startY, selectedElmX, selectedElmY, startW, startH, ratio, resizeStarted;
9412
      let width;
9413
      let height;
9414
      let startScrollWidth;
9415
      let startScrollHeight;
9416
      const isImage = elm => isNonNullable(elm) && (isImg(elm) || dom.is(elm, 'figure.image'));
9417
      const isMedia = elm => isMedia$2(elm) || dom.hasClass(elm, 'mce-preview-object');
9418
      const isEventOnImageOutsideRange = (evt, range) => {
9419
        if (isTouchEvent(evt)) {
9420
          const touch = evt.touches[0];
9421
          return isImage(evt.target) && !isXYWithinRange(touch.clientX, touch.clientY, range);
9422
        } else {
9423
          return isImage(evt.target) && !isXYWithinRange(evt.clientX, evt.clientY, range);
9424
        }
9425
      };
9426
      const contextMenuSelectImage = evt => {
9427
        const target = evt.target;
9428
        if (isEventOnImageOutsideRange(evt, editor.selection.getRng()) && !evt.isDefaultPrevented()) {
9429
          editor.selection.select(target);
9430
        }
9431
      };
9432
      const getResizeTargets = elm => {
9433
        if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
9434
          return [
9435
            elm,
9436
            elm.firstElementChild
9437
          ];
9438
        } else if (dom.is(elm, 'figure.image')) {
9439
          return [elm.querySelector('img')];
9440
        } else {
9441
          return [elm];
9442
        }
9443
      };
9444
      const isResizable = elm => {
9445
        const selector = getObjectResizing(editor);
9446
        if (!selector) {
9447
          return false;
9448
        }
9449
        if (elm.getAttribute('data-mce-resize') === 'false') {
9450
          return false;
9451
        }
9452
        if (elm === editor.getBody()) {
9453
          return false;
9454
        }
9455
        if (dom.hasClass(elm, 'mce-preview-object') && isNonNullable(elm.firstElementChild)) {
9456
          return is$1(SugarElement.fromDom(elm.firstElementChild), selector);
9457
        } else {
9458
          return is$1(SugarElement.fromDom(elm), selector);
9459
        }
9460
      };
9461
      const createGhostElement = elm => {
9462
        if (isMedia(elm)) {
9463
          return dom.create('img', { src: Env.transparentSrc });
9464
        } else {
9465
          return elm.cloneNode(true);
9466
        }
9467
      };
9468
      const setSizeProp = (element, name, value) => {
9469
        if (isNonNullable(value)) {
9470
          const targets = getResizeTargets(element);
9471
          each$e(targets, target => {
9472
            if (target.style[name] || !editor.schema.isValid(target.nodeName.toLowerCase(), name)) {
9473
              dom.setStyle(target, name, value);
9474
            } else {
9475
              dom.setAttrib(target, name, '' + value);
9476
            }
9477
          });
9478
        }
9479
      };
9480
      const setGhostElmSize = (ghostElm, width, height) => {
9481
        setSizeProp(ghostElm, 'width', width);
9482
        setSizeProp(ghostElm, 'height', height);
9483
      };
9484
      const resizeGhostElement = e => {
9485
        let deltaX, deltaY, proportional;
9486
        let resizeHelperX, resizeHelperY;
9487
        deltaX = e.screenX - startX;
9488
        deltaY = e.screenY - startY;
9489
        width = deltaX * selectedHandle[2] + startW;
9490
        height = deltaY * selectedHandle[3] + startH;
9491
        width = width < 5 ? 5 : width;
9492
        height = height < 5 ? 5 : height;
9493
        if ((isImage(selectedElm) || isMedia(selectedElm)) && getResizeImgProportional(editor) !== false) {
9494
          proportional = !VK.modifierPressed(e);
9495
        } else {
9496
          proportional = VK.modifierPressed(e);
9497
        }
9498
        if (proportional) {
9499
          if (abs(deltaX) > abs(deltaY)) {
9500
            height = round$1(width * ratio);
9501
            width = round$1(height / ratio);
9502
          } else {
9503
            width = round$1(height / ratio);
9504
            height = round$1(width * ratio);
9505
          }
9506
        }
9507
        setGhostElmSize(selectedElmGhost, width, height);
9508
        resizeHelperX = selectedHandle.startPos.x + deltaX;
9509
        resizeHelperY = selectedHandle.startPos.y + deltaY;
9510
        resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
9511
        resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
9512
        dom.setStyles(resizeHelper, {
9513
          left: resizeHelperX,
9514
          top: resizeHelperY,
9515
          display: 'block'
9516
        });
9517
        resizeHelper.innerHTML = width + ' &times; ' + height;
9518
        if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
9519
          dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));
9520
        }
9521
        if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
9522
          dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));
9523
        }
9524
        deltaX = rootElement.scrollWidth - startScrollWidth;
9525
        deltaY = rootElement.scrollHeight - startScrollHeight;
9526
        if (deltaX + deltaY !== 0) {
9527
          dom.setStyles(resizeHelper, {
9528
            left: resizeHelperX - deltaX,
9529
            top: resizeHelperY - deltaY
9530
          });
9531
        }
9532
        if (!resizeStarted) {
9533
          fireObjectResizeStart(editor, selectedElm, startW, startH, 'corner-' + selectedHandle.name);
9534
          resizeStarted = true;
9535
        }
9536
      };
9537
      const endGhostResize = () => {
9538
        const wasResizeStarted = resizeStarted;
9539
        resizeStarted = false;
9540
        if (wasResizeStarted) {
9541
          setSizeProp(selectedElm, 'width', width);
9542
          setSizeProp(selectedElm, 'height', height);
9543
        }
9544
        dom.unbind(editableDoc, 'mousemove', resizeGhostElement);
9545
        dom.unbind(editableDoc, 'mouseup', endGhostResize);
9546
        if (rootDocument !== editableDoc) {
9547
          dom.unbind(rootDocument, 'mousemove', resizeGhostElement);
9548
          dom.unbind(rootDocument, 'mouseup', endGhostResize);
9549
        }
9550
        dom.remove(selectedElmGhost);
9551
        dom.remove(resizeHelper);
9552
        dom.remove(resizeBackdrop);
9553
        showResizeRect(selectedElm);
9554
        if (wasResizeStarted) {
9555
          fireObjectResized(editor, selectedElm, width, height, 'corner-' + selectedHandle.name);
9556
          dom.setAttrib(selectedElm, 'style', dom.getAttrib(selectedElm, 'style'));
9557
        }
9558
        editor.nodeChanged();
9559
      };
9560
      const showResizeRect = targetElm => {
9561
        unbindResizeHandleEvents();
9562
        const position = dom.getPos(targetElm, rootElement);
9563
        const selectedElmX = position.x;
9564
        const selectedElmY = position.y;
9565
        const rect = targetElm.getBoundingClientRect();
9566
        const targetWidth = rect.width || rect.right - rect.left;
9567
        const targetHeight = rect.height || rect.bottom - rect.top;
9568
        if (selectedElm !== targetElm) {
9569
          hideResizeRect();
9570
          selectedElm = targetElm;
9571
          width = height = 0;
9572
        }
9573
        const e = editor.dispatch('ObjectSelected', { target: targetElm });
9574
        if (isResizable(targetElm) && !e.isDefaultPrevented()) {
9575
          each$d(resizeHandles, (handle, name) => {
9576
            const startDrag = e => {
9577
              const target = getResizeTargets(selectedElm)[0];
9578
              startX = e.screenX;
9579
              startY = e.screenY;
9580
              startW = target.clientWidth;
9581
              startH = target.clientHeight;
9582
              ratio = startH / startW;
9583
              selectedHandle = handle;
9584
              selectedHandle.name = name;
9585
              selectedHandle.startPos = {
9586
                x: targetWidth * handle[0] + selectedElmX,
9587
                y: targetHeight * handle[1] + selectedElmY
9588
              };
9589
              startScrollWidth = rootElement.scrollWidth;
9590
              startScrollHeight = rootElement.scrollHeight;
9591
              resizeBackdrop = dom.add(rootElement, 'div', {
9592
                'class': 'mce-resize-backdrop',
9593
                'data-mce-bogus': 'all'
9594
              });
9595
              dom.setStyles(resizeBackdrop, {
9596
                position: 'fixed',
9597
                left: '0',
9598
                top: '0',
9599
                width: '100%',
9600
                height: '100%'
9601
              });
9602
              selectedElmGhost = createGhostElement(selectedElm);
9603
              dom.addClass(selectedElmGhost, 'mce-clonedresizable');
9604
              dom.setAttrib(selectedElmGhost, 'data-mce-bogus', 'all');
9605
              selectedElmGhost.contentEditable = 'false';
9606
              dom.setStyles(selectedElmGhost, {
9607
                left: selectedElmX,
9608
                top: selectedElmY,
9609
                margin: 0
9610
              });
9611
              setGhostElmSize(selectedElmGhost, targetWidth, targetHeight);
9612
              selectedElmGhost.removeAttribute(elementSelectionAttr);
9613
              rootElement.appendChild(selectedElmGhost);
9614
              dom.bind(editableDoc, 'mousemove', resizeGhostElement);
9615
              dom.bind(editableDoc, 'mouseup', endGhostResize);
9616
              if (rootDocument !== editableDoc) {
9617
                dom.bind(rootDocument, 'mousemove', resizeGhostElement);
9618
                dom.bind(rootDocument, 'mouseup', endGhostResize);
9619
              }
9620
              resizeHelper = dom.add(rootElement, 'div', {
9621
                'class': 'mce-resize-helper',
9622
                'data-mce-bogus': 'all'
9623
              }, startW + ' &times; ' + startH);
9624
            };
9625
            let handleElm = dom.get('mceResizeHandle' + name);
9626
            if (handleElm) {
9627
              dom.remove(handleElm);
9628
            }
9629
            handleElm = dom.add(rootElement, 'div', {
9630
              'id': 'mceResizeHandle' + name,
9631
              'data-mce-bogus': 'all',
9632
              'class': 'mce-resizehandle',
9633
              'unselectable': true,
9634
              'style': 'cursor:' + name + '-resize; margin:0; padding:0'
9635
            });
9636
            dom.bind(handleElm, 'mousedown', e => {
9637
              e.stopImmediatePropagation();
9638
              e.preventDefault();
9639
              startDrag(e);
9640
            });
9641
            handle.elm = handleElm;
9642
            dom.setStyles(handleElm, {
9643
              left: targetWidth * handle[0] + selectedElmX - handleElm.offsetWidth / 2,
9644
              top: targetHeight * handle[1] + selectedElmY - handleElm.offsetHeight / 2
9645
            });
9646
          });
9647
        } else {
9648
          hideResizeRect(false);
9649
        }
9650
      };
9651
      const throttledShowResizeRect = first$1(showResizeRect, 0);
9652
      const hideResizeRect = (removeSelected = true) => {
9653
        throttledShowResizeRect.cancel();
9654
        unbindResizeHandleEvents();
9655
        if (selectedElm && removeSelected) {
9656
          selectedElm.removeAttribute(elementSelectionAttr);
9657
        }
9658
        each$d(resizeHandles, (value, name) => {
9659
          const handleElm = dom.get('mceResizeHandle' + name);
9660
          if (handleElm) {
9661
            dom.unbind(handleElm);
9662
            dom.remove(handleElm);
9663
          }
9664
        });
9665
      };
9666
      const isChildOrEqual = (node, parent) => dom.isChildOf(node, parent);
9667
      const updateResizeRect = e => {
9668
        if (resizeStarted || editor.removed || editor.composing) {
9669
          return;
9670
        }
9671
        const targetElm = e.type === 'mousedown' ? e.target : selection.getNode();
9672
        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();
9673
        const selectedValue = isNonNullable(controlElm) ? dom.getAttrib(controlElm, elementSelectionAttr, '1') : '1';
9674
        each$e(dom.select(`img[${ elementSelectionAttr }],hr[${ elementSelectionAttr }]`), img => {
9675
          img.removeAttribute(elementSelectionAttr);
9676
        });
9677
        if (isNonNullable(controlElm) && isChildOrEqual(controlElm, rootElement) && editor.hasFocus()) {
9678
          disableGeckoResize();
9679
          const startElm = selection.getStart(true);
9680
          if (isChildOrEqual(startElm, controlElm) && isChildOrEqual(selection.getEnd(true), controlElm)) {
9681
            dom.setAttrib(controlElm, elementSelectionAttr, selectedValue);
9682
            throttledShowResizeRect.throttle(controlElm);
9683
            return;
9684
          }
9685
        }
9686
        hideResizeRect();
9687
      };
9688
      const unbindResizeHandleEvents = () => {
9689
        each$d(resizeHandles, handle => {
9690
          if (handle.elm) {
9691
            dom.unbind(handle.elm);
9692
            delete handle.elm;
9693
          }
9694
        });
9695
      };
9696
      const disableGeckoResize = () => {
9697
        try {
9698
          editor.getDoc().execCommand('enableObjectResizing', false, 'false');
9699
        } catch (ex) {
9700
        }
9701
      };
9702
      editor.on('init', () => {
9703
        disableGeckoResize();
9704
        editor.on('NodeChange ResizeEditor ResizeWindow ResizeContent drop', updateResizeRect);
9705
        editor.on('keyup compositionend', e => {
9706
          if (selectedElm && selectedElm.nodeName === 'TABLE') {
9707
            updateResizeRect(e);
9708
          }
9709
        });
9710
        editor.on('hide blur', hideResizeRect);
9711
        editor.on('contextmenu longpress', contextMenuSelectImage, true);
9712
      });
9713
      editor.on('remove', unbindResizeHandleEvents);
9714
      const destroy = () => {
9715
        throttledShowResizeRect.cancel();
9716
        selectedElm = selectedElmGhost = resizeBackdrop = null;
9717
      };
9718
      return {
9719
        isResizable,
9720
        showResizeRect,
9721
        hideResizeRect,
9722
        updateResizeRect,
9723
        destroy
9724
      };
9725
    };
9726
 
9727
    const setStart = (rng, situ) => {
9728
      situ.fold(e => {
9729
        rng.setStartBefore(e.dom);
9730
      }, (e, o) => {
9731
        rng.setStart(e.dom, o);
9732
      }, e => {
9733
        rng.setStartAfter(e.dom);
9734
      });
9735
    };
9736
    const setFinish = (rng, situ) => {
9737
      situ.fold(e => {
9738
        rng.setEndBefore(e.dom);
9739
      }, (e, o) => {
9740
        rng.setEnd(e.dom, o);
9741
      }, e => {
9742
        rng.setEndAfter(e.dom);
9743
      });
9744
    };
9745
    const relativeToNative = (win, startSitu, finishSitu) => {
9746
      const range = win.document.createRange();
9747
      setStart(range, startSitu);
9748
      setFinish(range, finishSitu);
9749
      return range;
9750
    };
9751
    const exactToNative = (win, start, soffset, finish, foffset) => {
9752
      const rng = win.document.createRange();
9753
      rng.setStart(start.dom, soffset);
9754
      rng.setEnd(finish.dom, foffset);
9755
      return rng;
9756
    };
9757
 
9758
    const adt$3 = Adt.generate([
9759
      {
9760
        ltr: [
9761
          'start',
9762
          'soffset',
9763
          'finish',
9764
          'foffset'
9765
        ]
9766
      },
9767
      {
9768
        rtl: [
9769
          'start',
9770
          'soffset',
9771
          'finish',
9772
          'foffset'
9773
        ]
9774
      }
9775
    ]);
9776
    const fromRange = (win, type, range) => type(SugarElement.fromDom(range.startContainer), range.startOffset, SugarElement.fromDom(range.endContainer), range.endOffset);
9777
    const getRanges = (win, selection) => selection.match({
9778
      domRange: rng => {
9779
        return {
9780
          ltr: constant(rng),
9781
          rtl: Optional.none
9782
        };
9783
      },
9784
      relative: (startSitu, finishSitu) => {
9785
        return {
9786
          ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
9787
          rtl: cached(() => Optional.some(relativeToNative(win, finishSitu, startSitu)))
9788
        };
9789
      },
9790
      exact: (start, soffset, finish, foffset) => {
9791
        return {
9792
          ltr: cached(() => exactToNative(win, start, soffset, finish, foffset)),
9793
          rtl: cached(() => Optional.some(exactToNative(win, finish, foffset, start, soffset)))
9794
        };
9795
      }
9796
    });
9797
    const doDiagnose = (win, ranges) => {
9798
      const rng = ranges.ltr();
9799
      if (rng.collapsed) {
9800
        const reversed = ranges.rtl().filter(rev => rev.collapsed === false);
9801
        return reversed.map(rev => adt$3.rtl(SugarElement.fromDom(rev.endContainer), rev.endOffset, SugarElement.fromDom(rev.startContainer), rev.startOffset)).getOrThunk(() => fromRange(win, adt$3.ltr, rng));
9802
      } else {
9803
        return fromRange(win, adt$3.ltr, rng);
9804
      }
9805
    };
9806
    const diagnose = (win, selection) => {
9807
      const ranges = getRanges(win, selection);
9808
      return doDiagnose(win, ranges);
9809
    };
9810
    adt$3.ltr;
9811
    adt$3.rtl;
9812
 
9813
    const create$a = (start, soffset, finish, foffset) => ({
9814
      start,
9815
      soffset,
9816
      finish,
9817
      foffset
9818
    });
9819
    const SimRange = { create: create$a };
9820
 
9821
    const caretPositionFromPoint = (doc, x, y) => {
9822
      var _a, _b;
9823
      return Optional.from((_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y)).bind(pos => {
9824
        if (pos.offsetNode === null) {
9825
          return Optional.none();
9826
        }
9827
        const r = doc.dom.createRange();
9828
        r.setStart(pos.offsetNode, pos.offset);
9829
        r.collapse();
9830
        return Optional.some(r);
9831
      });
9832
    };
9833
    const caretRangeFromPoint = (doc, x, y) => {
9834
      var _a, _b;
9835
      return Optional.from((_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0 ? void 0 : _b.call(_a, x, y));
9836
    };
9837
    const availableSearch = (() => {
9838
      if (document.caretPositionFromPoint) {
9839
        return caretPositionFromPoint;
9840
      } else if (document.caretRangeFromPoint) {
9841
        return caretRangeFromPoint;
9842
      } else {
9843
        return Optional.none;
9844
      }
9845
    })();
9846
    const fromPoint$1 = (win, x, y) => {
9847
      const doc = SugarElement.fromDom(win.document);
9848
      return availableSearch(doc, x, y).map(rng => SimRange.create(SugarElement.fromDom(rng.startContainer), rng.startOffset, SugarElement.fromDom(rng.endContainer), rng.endOffset));
9849
    };
9850
 
9851
    const adt$2 = Adt.generate([
9852
      { before: ['element'] },
9853
      {
9854
        on: [
9855
          'element',
9856
          'offset'
9857
        ]
9858
      },
9859
      { after: ['element'] }
9860
    ]);
9861
    const cata = (subject, onBefore, onOn, onAfter) => subject.fold(onBefore, onOn, onAfter);
9862
    const getStart$2 = situ => situ.fold(identity, identity, identity);
9863
    const before$1 = adt$2.before;
9864
    const on = adt$2.on;
9865
    const after$1 = adt$2.after;
9866
    const Situ = {
9867
      before: before$1,
9868
      on,
9869
      after: after$1,
9870
      cata,
9871
      getStart: getStart$2
9872
    };
9873
 
9874
    const adt$1 = Adt.generate([
9875
      { domRange: ['rng'] },
9876
      {
9877
        relative: [
9878
          'startSitu',
9879
          'finishSitu'
9880
        ]
9881
      },
9882
      {
9883
        exact: [
9884
          'start',
9885
          'soffset',
9886
          'finish',
9887
          'foffset'
9888
        ]
9889
      }
9890
    ]);
9891
    const exactFromRange = simRange => adt$1.exact(simRange.start, simRange.soffset, simRange.finish, simRange.foffset);
9892
    const getStart$1 = selection => selection.match({
9893
      domRange: rng => SugarElement.fromDom(rng.startContainer),
9894
      relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
9895
      exact: (start, _soffset, _finish, _foffset) => start
9896
    });
9897
    const domRange = adt$1.domRange;
9898
    const relative = adt$1.relative;
9899
    const exact = adt$1.exact;
9900
    const getWin = selection => {
9901
      const start = getStart$1(selection);
9902
      return defaultView(start);
9903
    };
9904
    const range = SimRange.create;
9905
    const SimSelection = {
9906
      domRange,
9907
      relative,
9908
      exact,
9909
      exactFromRange,
9910
      getWin,
9911
      range
9912
    };
9913
 
9914
    const beforeSpecial = (element, offset) => {
9915
      const name$1 = name(element);
9916
      if ('input' === name$1) {
9917
        return Situ.after(element);
9918
      } else if (!contains$2([
9919
          'br',
9920
          'img'
9921
        ], name$1)) {
9922
        return Situ.on(element, offset);
9923
      } else {
9924
        return offset === 0 ? Situ.before(element) : Situ.after(element);
9925
      }
9926
    };
9927
    const preprocessRelative = (startSitu, finishSitu) => {
9928
      const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
9929
      const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
9930
      return SimSelection.relative(start, finish);
9931
    };
9932
    const preprocessExact = (start, soffset, finish, foffset) => {
9933
      const startSitu = beforeSpecial(start, soffset);
9934
      const finishSitu = beforeSpecial(finish, foffset);
9935
      return SimSelection.relative(startSitu, finishSitu);
9936
    };
9937
    const preprocess = selection => selection.match({
9938
      domRange: rng => {
9939
        const start = SugarElement.fromDom(rng.startContainer);
9940
        const finish = SugarElement.fromDom(rng.endContainer);
9941
        return preprocessExact(start, rng.startOffset, finish, rng.endOffset);
9942
      },
9943
      relative: preprocessRelative,
9944
      exact: preprocessExact
9945
    });
9946
 
9947
    const fromElements = (elements, scope) => {
9948
      const doc = scope || document;
9949
      const fragment = doc.createDocumentFragment();
9950
      each$e(elements, element => {
9951
        fragment.appendChild(element.dom);
9952
      });
9953
      return SugarElement.fromDom(fragment);
9954
    };
9955
 
9956
    const toNative = selection => {
9957
      const win = SimSelection.getWin(selection).dom;
9958
      const getDomRange = (start, soffset, finish, foffset) => exactToNative(win, start, soffset, finish, foffset);
9959
      const filtered = preprocess(selection);
9960
      return diagnose(win, filtered).match({
9961
        ltr: getDomRange,
9962
        rtl: getDomRange
9963
      });
9964
    };
9965
    const getAtPoint = (win, x, y) => fromPoint$1(win, x, y);
9966
 
9967
    const fromPoint = (clientX, clientY, doc) => {
9968
      const win = defaultView(SugarElement.fromDom(doc));
9969
      return getAtPoint(win.dom, clientX, clientY).map(simRange => {
9970
        const rng = doc.createRange();
9971
        rng.setStart(simRange.start.dom, simRange.soffset);
9972
        rng.setEnd(simRange.finish.dom, simRange.foffset);
9973
        return rng;
9974
      }).getOrUndefined();
9975
    };
9976
 
9977
    const isEq$4 = (rng1, rng2) => {
9978
      return isNonNullable(rng1) && isNonNullable(rng2) && (rng1.startContainer === rng2.startContainer && rng1.startOffset === rng2.startOffset) && (rng1.endContainer === rng2.endContainer && rng1.endOffset === rng2.endOffset);
9979
    };
9980
 
9981
    const findParent = (node, rootNode, predicate) => {
9982
      let currentNode = node;
9983
      while (currentNode && currentNode !== rootNode) {
9984
        if (predicate(currentNode)) {
9985
          return currentNode;
9986
        }
9987
        currentNode = currentNode.parentNode;
9988
      }
9989
      return null;
9990
    };
9991
    const hasParent$1 = (node, rootNode, predicate) => findParent(node, rootNode, predicate) !== null;
9992
    const hasParentWithName = (node, rootNode, name) => hasParent$1(node, rootNode, node => node.nodeName === name);
9993
    const isCeFalseCaretContainer = (node, rootNode) => isCaretContainer$2(node) && !hasParent$1(node, rootNode, isCaretNode);
9994
    const hasBrBeforeAfter = (dom, node, left) => {
9995
      const parentNode = node.parentNode;
9996
      if (parentNode) {
9997
        const walker = new DomTreeWalker(node, dom.getParent(parentNode, dom.isBlock) || dom.getRoot());
9998
        let currentNode;
9999
        while (currentNode = walker[left ? 'prev' : 'next']()) {
10000
          if (isBr$6(currentNode)) {
10001
            return true;
10002
          }
10003
        }
10004
      }
10005
      return false;
10006
    };
10007
    const isPrevNode = (node, name) => {
10008
      var _a;
10009
      return ((_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.nodeName) === name;
10010
    };
10011
    const hasContentEditableFalseParent = (root, node) => {
10012
      let currentNode = node;
10013
      while (currentNode && currentNode !== root) {
10014
        if (isContentEditableFalse$b(currentNode)) {
10015
          return true;
10016
        }
10017
        currentNode = currentNode.parentNode;
10018
      }
10019
      return false;
10020
    };
10021
    const findTextNodeRelative = (dom, isAfterNode, collapsed, left, startNode) => {
10022
      const body = dom.getRoot();
10023
      const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
10024
      const parentNode = startNode.parentNode;
10025
      let lastInlineElement;
10026
      let node;
10027
      if (!parentNode) {
10028
        return Optional.none();
10029
      }
10030
      const parentBlockContainer = dom.getParent(parentNode, dom.isBlock) || body;
10031
      if (left && isBr$6(startNode) && isAfterNode && dom.isEmpty(parentBlockContainer)) {
10032
        return Optional.some(CaretPosition(parentNode, dom.nodeIndex(startNode)));
10033
      }
10034
      const walker = new DomTreeWalker(startNode, parentBlockContainer);
10035
      while (node = walker[left ? 'prev' : 'next']()) {
10036
        if (dom.getContentEditableParent(node) === 'false' || isCeFalseCaretContainer(node, body)) {
10037
          return Optional.none();
10038
        }
10039
        if (isText$a(node) && node.data.length > 0) {
10040
          if (!hasParentWithName(node, body, 'A')) {
10041
            return Optional.some(CaretPosition(node, left ? node.data.length : 0));
10042
          }
10043
          return Optional.none();
10044
        }
10045
        if (dom.isBlock(node) || nonEmptyElementsMap[node.nodeName.toLowerCase()]) {
10046
          return Optional.none();
10047
        }
10048
        lastInlineElement = node;
10049
      }
10050
      if (isComment(lastInlineElement)) {
10051
        return Optional.none();
10052
      }
10053
      if (collapsed && lastInlineElement) {
10054
        return Optional.some(CaretPosition(lastInlineElement, 0));
10055
      }
10056
      return Optional.none();
10057
    };
10058
    const normalizeEndPoint = (dom, collapsed, start, rng) => {
10059
      const body = dom.getRoot();
10060
      let node;
10061
      let normalized = false;
10062
      let container = start ? rng.startContainer : rng.endContainer;
10063
      let offset = start ? rng.startOffset : rng.endOffset;
10064
      const isAfterNode = isElement$6(container) && offset === container.childNodes.length;
10065
      const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
10066
      let directionLeft = start;
10067
      if (isCaretContainer$2(container)) {
10068
        return Optional.none();
10069
      }
10070
      if (isElement$6(container) && offset > container.childNodes.length - 1) {
10071
        directionLeft = false;
10072
      }
10073
      if (isDocument$1(container)) {
10074
        container = body;
10075
        offset = 0;
10076
      }
10077
      if (container === body) {
10078
        if (directionLeft) {
10079
          node = container.childNodes[offset > 0 ? offset - 1 : 0];
10080
          if (node) {
10081
            if (isCaretContainer$2(node)) {
10082
              return Optional.none();
10083
            }
10084
            if (nonEmptyElementsMap[node.nodeName] || isTable$2(node)) {
10085
              return Optional.none();
10086
            }
10087
          }
10088
        }
10089
        if (container.hasChildNodes()) {
10090
          offset = Math.min(!directionLeft && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1);
10091
          container = container.childNodes[offset];
10092
          offset = isText$a(container) && isAfterNode ? container.data.length : 0;
10093
          if (!collapsed && container === body.lastChild && isTable$2(container)) {
10094
            return Optional.none();
10095
          }
10096
          if (hasContentEditableFalseParent(body, container) || isCaretContainer$2(container)) {
10097
            return Optional.none();
10098
          }
10099
          if (isDetails(container)) {
10100
            return Optional.none();
10101
          }
10102
          if (container.hasChildNodes() && !isTable$2(container)) {
10103
            node = container;
10104
            const walker = new DomTreeWalker(container, body);
10105
            do {
10106
              if (isContentEditableFalse$b(node) || isCaretContainer$2(node)) {
10107
                normalized = false;
10108
                break;
10109
              }
10110
              if (isText$a(node) && node.data.length > 0) {
10111
                offset = directionLeft ? 0 : node.data.length;
10112
                container = node;
10113
                normalized = true;
10114
                break;
10115
              }
10116
              if (nonEmptyElementsMap[node.nodeName.toLowerCase()] && !isTableCellOrCaption(node)) {
10117
                offset = dom.nodeIndex(node);
10118
                container = node.parentNode;
10119
                if (!directionLeft) {
10120
                  offset++;
10121
                }
10122
                normalized = true;
10123
                break;
10124
              }
10125
            } while (node = directionLeft ? walker.next() : walker.prev());
10126
          }
10127
        }
10128
      }
10129
      if (collapsed) {
10130
        if (isText$a(container) && offset === 0) {
10131
          findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(pos => {
10132
            container = pos.container();
10133
            offset = pos.offset();
10134
            normalized = true;
10135
          });
10136
        }
10137
        if (isElement$6(container)) {
10138
          node = container.childNodes[offset];
10139
          if (!node) {
10140
            node = container.childNodes[offset - 1];
10141
          }
10142
          if (node && isBr$6(node) && !isPrevNode(node, 'A') && !hasBrBeforeAfter(dom, node, false) && !hasBrBeforeAfter(dom, node, true)) {
10143
            findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(pos => {
10144
              container = pos.container();
10145
              offset = pos.offset();
10146
              normalized = true;
10147
            });
10148
          }
10149
        }
10150
      }
10151
      if (directionLeft && !collapsed && isText$a(container) && offset === container.data.length) {
10152
        findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(pos => {
10153
          container = pos.container();
10154
          offset = pos.offset();
10155
          normalized = true;
10156
        });
10157
      }
10158
      return normalized && container ? Optional.some(CaretPosition(container, offset)) : Optional.none();
10159
    };
10160
    const normalize$2 = (dom, rng) => {
10161
      const collapsed = rng.collapsed, normRng = rng.cloneRange();
10162
      const startPos = CaretPosition.fromRangeStart(rng);
10163
      normalizeEndPoint(dom, collapsed, true, normRng).each(pos => {
10164
        if (!collapsed || !CaretPosition.isAbove(startPos, pos)) {
10165
          normRng.setStart(pos.container(), pos.offset());
10166
        }
10167
      });
10168
      if (!collapsed) {
10169
        normalizeEndPoint(dom, collapsed, false, normRng).each(pos => {
10170
          normRng.setEnd(pos.container(), pos.offset());
10171
        });
10172
      }
10173
      if (collapsed) {
10174
        normRng.collapse(true);
10175
      }
10176
      return isEq$4(rng, normRng) ? Optional.none() : Optional.some(normRng);
10177
    };
10178
 
10179
    const splitText = (node, offset) => {
10180
      return node.splitText(offset);
10181
    };
10182
    const split = rng => {
10183
      let startContainer = rng.startContainer, startOffset = rng.startOffset, endContainer = rng.endContainer, endOffset = rng.endOffset;
10184
      if (startContainer === endContainer && isText$a(startContainer)) {
10185
        if (startOffset > 0 && startOffset < startContainer.data.length) {
10186
          endContainer = splitText(startContainer, startOffset);
10187
          startContainer = endContainer.previousSibling;
10188
          if (endOffset > startOffset) {
10189
            endOffset = endOffset - startOffset;
10190
            const newContainer = splitText(endContainer, endOffset).previousSibling;
10191
            startContainer = endContainer = newContainer;
10192
            endOffset = newContainer.data.length;
10193
            startOffset = 0;
10194
          } else {
10195
            endOffset = 0;
10196
          }
10197
        }
10198
      } else {
10199
        if (isText$a(startContainer) && startOffset > 0 && startOffset < startContainer.data.length) {
10200
          startContainer = splitText(startContainer, startOffset);
10201
          startOffset = 0;
10202
        }
10203
        if (isText$a(endContainer) && endOffset > 0 && endOffset < endContainer.data.length) {
10204
          const newContainer = splitText(endContainer, endOffset).previousSibling;
10205
          endContainer = newContainer;
10206
          endOffset = newContainer.data.length;
10207
        }
10208
      }
10209
      return {
10210
        startContainer,
10211
        startOffset,
10212
        endContainer,
10213
        endOffset
10214
      };
10215
    };
10216
 
10217
    const RangeUtils = dom => {
10218
      const walk = (rng, callback) => {
10219
        return walk$3(dom, rng, callback);
10220
      };
10221
      const split$1 = split;
10222
      const normalize = rng => {
10223
        return normalize$2(dom, rng).fold(never, normalizedRng => {
10224
          rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset);
10225
          rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset);
10226
          return true;
10227
        });
10228
      };
10229
      const expand = (rng, options = { type: 'word' }) => {
10230
        if (options.type === 'word') {
10231
          const rangeLike = expandRng(dom, rng, [{ inline: 'span' }]);
10232
          const newRange = dom.createRng();
10233
          newRange.setStart(rangeLike.startContainer, rangeLike.startOffset);
10234
          newRange.setEnd(rangeLike.endContainer, rangeLike.endOffset);
10235
          return newRange;
10236
        }
10237
        return rng;
10238
      };
10239
      return {
10240
        walk,
10241
        split: split$1,
10242
        expand,
10243
        normalize
10244
      };
10245
    };
10246
    RangeUtils.compareRanges = isEq$4;
10247
    RangeUtils.getCaretRangeFromPoint = fromPoint;
10248
    RangeUtils.getSelectedNode = getSelectedNode;
10249
    RangeUtils.getNode = getNode$1;
10250
 
10251
    const Dimension = (name, getOffset) => {
10252
      const set = (element, h) => {
10253
        if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
10254
          throw new Error(name + '.set accepts only positive integer values. Value was ' + h);
10255
        }
10256
        const dom = element.dom;
10257
        if (isSupported(dom)) {
10258
          dom.style[name] = h + 'px';
10259
        }
10260
      };
10261
      const get = element => {
10262
        const r = getOffset(element);
10263
        if (r <= 0 || r === null) {
10264
          const css = get$7(element, name);
10265
          return parseFloat(css) || 0;
10266
        }
10267
        return r;
10268
      };
10269
      const getOuter = get;
10270
      const aggregate = (element, properties) => foldl(properties, (acc, property) => {
10271
        const val = get$7(element, property);
10272
        const value = val === undefined ? 0 : parseInt(val, 10);
10273
        return isNaN(value) ? acc : acc + value;
10274
      }, 0);
10275
      const max = (element, value, properties) => {
10276
        const cumulativeInclusions = aggregate(element, properties);
10277
        const absoluteMax = value > cumulativeInclusions ? value - cumulativeInclusions : 0;
10278
        return absoluteMax;
10279
      };
10280
      return {
10281
        set,
10282
        get,
10283
        getOuter,
10284
        aggregate,
10285
        max
10286
      };
10287
    };
10288
 
10289
    const api = Dimension('height', element => {
10290
      const dom = element.dom;
10291
      return inBody(element) ? dom.getBoundingClientRect().height : dom.offsetHeight;
10292
    });
10293
    const get$2 = element => api.get(element);
10294
 
10295
    const getDocument = () => SugarElement.fromDom(document);
10296
 
10297
    const walkUp = (navigation, doc) => {
10298
      const frame = navigation.view(doc);
10299
      return frame.fold(constant([]), f => {
10300
        const parent = navigation.owner(f);
10301
        const rest = walkUp(navigation, parent);
10302
        return [f].concat(rest);
10303
      });
10304
    };
10305
    const pathTo = (element, navigation) => {
10306
      const d = navigation.owner(element);
10307
      return walkUp(navigation, d);
10308
    };
10309
 
10310
    const view = doc => {
10311
      var _a;
10312
      const element = doc.dom === document ? Optional.none() : Optional.from((_a = doc.dom.defaultView) === null || _a === void 0 ? void 0 : _a.frameElement);
10313
      return element.map(SugarElement.fromDom);
10314
    };
10315
    const owner = element => documentOrOwner(element);
10316
 
10317
    var Navigation = /*#__PURE__*/Object.freeze({
10318
        __proto__: null,
10319
        view: view,
10320
        owner: owner
10321
    });
10322
 
10323
    const find = element => {
10324
      const doc = getDocument();
10325
      const scroll = get$5(doc);
10326
      const frames = pathTo(element, Navigation);
10327
      const offset = viewport(element);
10328
      const r = foldr(frames, (b, a) => {
10329
        const loc = viewport(a);
10330
        return {
10331
          left: b.left + loc.left,
10332
          top: b.top + loc.top
10333
        };
10334
      }, {
10335
        left: 0,
10336
        top: 0
10337
      });
10338
      return SugarPosition(r.left + offset.left + scroll.left, r.top + offset.top + scroll.top);
10339
    };
10340
 
10341
    const excludeFromDescend = element => name(element) === 'textarea';
10342
    const fireScrollIntoViewEvent = (editor, data) => {
10343
      const scrollEvent = editor.dispatch('ScrollIntoView', data);
10344
      return scrollEvent.isDefaultPrevented();
10345
    };
10346
    const fireAfterScrollIntoViewEvent = (editor, data) => {
10347
      editor.dispatch('AfterScrollIntoView', data);
10348
    };
10349
    const descend = (element, offset) => {
10350
      const children = children$1(element);
10351
      if (children.length === 0 || excludeFromDescend(element)) {
10352
        return {
10353
          element,
10354
          offset
10355
        };
10356
      } else if (offset < children.length && !excludeFromDescend(children[offset])) {
10357
        return {
10358
          element: children[offset],
10359
          offset: 0
10360
        };
10361
      } else {
10362
        const last = children[children.length - 1];
10363
        if (excludeFromDescend(last)) {
10364
          return {
10365
            element,
10366
            offset
10367
          };
10368
        } else {
10369
          if (name(last) === 'img') {
10370
            return {
10371
              element: last,
10372
              offset: 1
10373
            };
10374
          } else if (isText$b(last)) {
10375
            return {
10376
              element: last,
10377
              offset: get$3(last).length
10378
            };
10379
          } else {
10380
            return {
10381
              element: last,
10382
              offset: children$1(last).length
10383
            };
10384
          }
10385
        }
10386
      }
10387
    };
10388
    const markerInfo = (element, cleanupFun) => {
10389
      const pos = absolute(element);
10390
      const height = get$2(element);
10391
      return {
10392
        element,
10393
        bottom: pos.top + height,
10394
        height,
10395
        pos,
10396
        cleanup: cleanupFun
10397
      };
10398
    };
10399
    const createMarker$1 = (element, offset) => {
10400
      const startPoint = descend(element, offset);
10401
      const span = SugarElement.fromHtml('<span data-mce-bogus="all" style="display: inline-block;">' + ZWSP$1 + '</span>');
10402
      before$3(startPoint.element, span);
10403
      return markerInfo(span, () => remove$5(span));
10404
    };
10405
    const elementMarker = element => markerInfo(SugarElement.fromDom(element), noop);
10406
    const withMarker = (editor, f, rng, alignToTop) => {
10407
      preserveWith(editor, (_s, _e) => applyWithMarker(editor, f, rng, alignToTop), rng);
10408
    };
10409
    const withScrollEvents = (editor, doc, f, marker, alignToTop) => {
10410
      const data = {
10411
        elm: marker.element.dom,
10412
        alignToTop
10413
      };
10414
      if (fireScrollIntoViewEvent(editor, data)) {
10415
        return;
10416
      }
10417
      const scrollTop = get$5(doc).top;
10418
      f(editor, doc, scrollTop, marker, alignToTop);
10419
      fireAfterScrollIntoViewEvent(editor, data);
10420
    };
10421
    const applyWithMarker = (editor, f, rng, alignToTop) => {
10422
      const body = SugarElement.fromDom(editor.getBody());
10423
      const doc = SugarElement.fromDom(editor.getDoc());
10424
      reflow(body);
10425
      const marker = createMarker$1(SugarElement.fromDom(rng.startContainer), rng.startOffset);
10426
      withScrollEvents(editor, doc, f, marker, alignToTop);
10427
      marker.cleanup();
10428
    };
10429
    const withElement = (editor, element, f, alignToTop) => {
10430
      const doc = SugarElement.fromDom(editor.getDoc());
10431
      withScrollEvents(editor, doc, f, elementMarker(element), alignToTop);
10432
    };
10433
    const preserveWith = (editor, f, rng) => {
10434
      const startElement = rng.startContainer;
10435
      const startOffset = rng.startOffset;
10436
      const endElement = rng.endContainer;
10437
      const endOffset = rng.endOffset;
10438
      f(SugarElement.fromDom(startElement), SugarElement.fromDom(endElement));
10439
      const newRng = editor.dom.createRng();
10440
      newRng.setStart(startElement, startOffset);
10441
      newRng.setEnd(endElement, endOffset);
10442
      editor.selection.setRng(rng);
10443
    };
10444
    const scrollToMarker = (editor, marker, viewHeight, alignToTop, doc) => {
10445
      const pos = marker.pos;
10446
      if (alignToTop) {
10447
        to(pos.left, pos.top, doc);
10448
      } else {
10449
        const y = pos.top - viewHeight + marker.height;
10450
        to(-editor.getBody().getBoundingClientRect().left, y, doc);
10451
      }
10452
    };
10453
    const intoWindowIfNeeded = (editor, doc, scrollTop, viewHeight, marker, alignToTop) => {
10454
      const viewportBottom = viewHeight + scrollTop;
10455
      const markerTop = marker.pos.top;
10456
      const markerBottom = marker.bottom;
10457
      const largerThanViewport = markerBottom - markerTop >= viewHeight;
10458
      if (markerTop < scrollTop) {
10459
        scrollToMarker(editor, marker, viewHeight, alignToTop !== false, doc);
10460
      } else if (markerTop > viewportBottom) {
10461
        const align = largerThanViewport ? alignToTop !== false : alignToTop === true;
10462
        scrollToMarker(editor, marker, viewHeight, align, doc);
10463
      } else if (markerBottom > viewportBottom && !largerThanViewport) {
10464
        scrollToMarker(editor, marker, viewHeight, alignToTop === true, doc);
10465
      }
10466
    };
10467
    const intoWindow = (editor, doc, scrollTop, marker, alignToTop) => {
10468
      const viewHeight = defaultView(doc).dom.innerHeight;
10469
      intoWindowIfNeeded(editor, doc, scrollTop, viewHeight, marker, alignToTop);
10470
    };
10471
    const intoFrame = (editor, doc, scrollTop, marker, alignToTop) => {
10472
      const frameViewHeight = defaultView(doc).dom.innerHeight;
10473
      intoWindowIfNeeded(editor, doc, scrollTop, frameViewHeight, marker, alignToTop);
10474
      const op = find(marker.element);
10475
      const viewportBounds = getBounds(window);
10476
      if (op.top < viewportBounds.y) {
10477
        intoView(marker.element, alignToTop !== false);
10478
      } else if (op.top > viewportBounds.bottom) {
10479
        intoView(marker.element, alignToTop === true);
10480
      }
10481
    };
10482
    const rangeIntoWindow = (editor, rng, alignToTop) => withMarker(editor, intoWindow, rng, alignToTop);
10483
    const elementIntoWindow = (editor, element, alignToTop) => withElement(editor, element, intoWindow, alignToTop);
10484
    const rangeIntoFrame = (editor, rng, alignToTop) => withMarker(editor, intoFrame, rng, alignToTop);
10485
    const elementIntoFrame = (editor, element, alignToTop) => withElement(editor, element, intoFrame, alignToTop);
10486
    const scrollElementIntoView = (editor, element, alignToTop) => {
10487
      const scroller = editor.inline ? elementIntoWindow : elementIntoFrame;
10488
      scroller(editor, element, alignToTop);
10489
    };
10490
    const scrollRangeIntoView = (editor, rng, alignToTop) => {
10491
      const scroller = editor.inline ? rangeIntoWindow : rangeIntoFrame;
10492
      scroller(editor, rng, alignToTop);
10493
    };
10494
 
10495
    const focus$1 = (element, preventScroll = false) => element.dom.focus({ preventScroll });
10496
    const hasFocus$1 = element => {
10497
      const root = getRootNode(element).dom;
10498
      return element.dom === root.activeElement;
10499
    };
10500
    const active$1 = (root = getDocument()) => Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
10501
    const search = element => active$1(getRootNode(element)).filter(e => element.dom.contains(e.dom));
10502
 
10503
    const clamp$1 = (offset, element) => {
10504
      const max = isText$b(element) ? get$3(element).length : children$1(element).length + 1;
10505
      if (offset > max) {
10506
        return max;
10507
      } else if (offset < 0) {
10508
        return 0;
10509
      }
10510
      return offset;
10511
    };
10512
    const normalizeRng = rng => SimSelection.range(rng.start, clamp$1(rng.soffset, rng.start), rng.finish, clamp$1(rng.foffset, rng.finish));
10513
    const isOrContains = (root, elm) => !isRestrictedNode(elm.dom) && (contains(root, elm) || eq(root, elm));
10514
    const isRngInRoot = root => rng => isOrContains(root, rng.start) && isOrContains(root, rng.finish);
10515
    const shouldStore = editor => editor.inline || Env.browser.isFirefox();
10516
    const nativeRangeToSelectionRange = r => SimSelection.range(SugarElement.fromDom(r.startContainer), r.startOffset, SugarElement.fromDom(r.endContainer), r.endOffset);
10517
    const readRange = win => {
10518
      const selection = win.getSelection();
10519
      const rng = !selection || selection.rangeCount === 0 ? Optional.none() : Optional.from(selection.getRangeAt(0));
10520
      return rng.map(nativeRangeToSelectionRange);
10521
    };
10522
    const getBookmark = root => {
10523
      const win = defaultView(root);
10524
      return readRange(win.dom).filter(isRngInRoot(root));
10525
    };
10526
    const validate = (root, bookmark) => Optional.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng);
10527
    const bookmarkToNativeRng = bookmark => {
10528
      const rng = document.createRange();
10529
      try {
10530
        rng.setStart(bookmark.start.dom, bookmark.soffset);
10531
        rng.setEnd(bookmark.finish.dom, bookmark.foffset);
10532
        return Optional.some(rng);
10533
      } catch (_) {
10534
        return Optional.none();
10535
      }
10536
    };
10537
    const store = editor => {
10538
      const newBookmark = shouldStore(editor) ? getBookmark(SugarElement.fromDom(editor.getBody())) : Optional.none();
10539
      editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
10540
    };
10541
    const getRng = editor => {
10542
      const bookmark = editor.bookmark ? editor.bookmark : Optional.none();
10543
      return bookmark.bind(x => validate(SugarElement.fromDom(editor.getBody()), x)).bind(bookmarkToNativeRng);
10544
    };
10545
    const restore = editor => {
10546
      getRng(editor).each(rng => editor.selection.setRng(rng));
10547
    };
10548
 
10549
    const isEditorUIElement$1 = elm => {
10550
      const className = elm.className.toString();
10551
      return className.indexOf('tox-') !== -1 || className.indexOf('mce-') !== -1;
10552
    };
10553
    const FocusManager = { isEditorUIElement: isEditorUIElement$1 };
10554
 
10555
    const wrappedSetTimeout = (callback, time) => {
10556
      if (!isNumber(time)) {
10557
        time = 0;
10558
      }
10559
      return setTimeout(callback, time);
10560
    };
10561
    const wrappedSetInterval = (callback, time) => {
10562
      if (!isNumber(time)) {
10563
        time = 0;
10564
      }
10565
      return setInterval(callback, time);
10566
    };
10567
    const Delay = {
10568
      setEditorTimeout: (editor, callback, time) => {
10569
        return wrappedSetTimeout(() => {
10570
          if (!editor.removed) {
10571
            callback();
10572
          }
10573
        }, time);
10574
      },
10575
      setEditorInterval: (editor, callback, time) => {
10576
        const timer = wrappedSetInterval(() => {
10577
          if (!editor.removed) {
10578
            callback();
10579
          } else {
10580
            clearInterval(timer);
10581
          }
10582
        }, time);
10583
        return timer;
10584
      }
10585
    };
10586
 
10587
    const isManualNodeChange = e => {
10588
      return e.type === 'nodechange' && e.selectionChange;
10589
    };
10590
    const registerPageMouseUp = (editor, throttledStore) => {
10591
      const mouseUpPage = () => {
10592
        throttledStore.throttle();
10593
      };
10594
      DOMUtils.DOM.bind(document, 'mouseup', mouseUpPage);
10595
      editor.on('remove', () => {
10596
        DOMUtils.DOM.unbind(document, 'mouseup', mouseUpPage);
10597
      });
10598
    };
10599
    const registerMouseUp = (editor, throttledStore) => {
10600
      editor.on('mouseup touchend', _e => {
10601
        throttledStore.throttle();
10602
      });
10603
    };
10604
    const registerEditorEvents = (editor, throttledStore) => {
10605
      registerMouseUp(editor, throttledStore);
10606
      editor.on('keyup NodeChange AfterSetSelectionRange', e => {
10607
        if (!isManualNodeChange(e)) {
10608
          store(editor);
10609
        }
10610
      });
10611
    };
10612
    const register$6 = editor => {
10613
      const throttledStore = first$1(() => {
10614
        store(editor);
10615
      }, 0);
10616
      editor.on('init', () => {
10617
        if (editor.inline) {
10618
          registerPageMouseUp(editor, throttledStore);
10619
        }
10620
        registerEditorEvents(editor, throttledStore);
10621
      });
10622
      editor.on('remove', () => {
10623
        throttledStore.cancel();
10624
      });
10625
    };
10626
 
10627
    let documentFocusInHandler;
10628
    const DOM$9 = DOMUtils.DOM;
10629
    const isEditorUIElement = elm => {
10630
      return isElement$6(elm) && FocusManager.isEditorUIElement(elm);
10631
    };
10632
    const isEditorContentAreaElement = elm => {
10633
      const classList = elm.classList;
10634
      if (classList !== undefined) {
10635
        return classList.contains('tox-edit-area') || classList.contains('tox-edit-area__iframe') || classList.contains('mce-content-body');
10636
      } else {
10637
        return false;
10638
      }
10639
    };
10640
    const isUIElement = (editor, elm) => {
10641
      const customSelector = getCustomUiSelector(editor);
10642
      const parent = DOM$9.getParent(elm, elm => {
10643
        return isEditorUIElement(elm) || (customSelector ? editor.dom.is(elm, customSelector) : false);
10644
      });
10645
      return parent !== null;
10646
    };
10647
    const getActiveElement = editor => {
10648
      try {
10649
        const root = getRootNode(SugarElement.fromDom(editor.getElement()));
10650
        return active$1(root).fold(() => document.body, x => x.dom);
10651
      } catch (ex) {
10652
        return document.body;
10653
      }
10654
    };
10655
    const registerEvents$1 = (editorManager, e) => {
10656
      const editor = e.editor;
10657
      register$6(editor);
10658
      const toggleContentAreaOnFocus = (editor, fn) => {
10659
        if (shouldHighlightOnFocus(editor) && editor.inline !== true) {
10660
          const contentArea = SugarElement.fromDom(editor.getContainer());
10661
          fn(contentArea, 'tox-edit-focus');
10662
        }
10663
      };
10664
      editor.on('focusin', () => {
10665
        const focusedEditor = editorManager.focusedEditor;
10666
        if (isEditorContentAreaElement(getActiveElement(editor))) {
10667
          toggleContentAreaOnFocus(editor, add$2);
10668
        }
10669
        if (focusedEditor !== editor) {
10670
          if (focusedEditor) {
10671
            focusedEditor.dispatch('blur', { focusedEditor: editor });
10672
          }
10673
          editorManager.setActive(editor);
10674
          editorManager.focusedEditor = editor;
10675
          editor.dispatch('focus', { blurredEditor: focusedEditor });
10676
          editor.focus(true);
10677
        }
10678
      });
10679
      editor.on('focusout', () => {
10680
        Delay.setEditorTimeout(editor, () => {
10681
          const focusedEditor = editorManager.focusedEditor;
10682
          if (!isEditorContentAreaElement(getActiveElement(editor)) || focusedEditor !== editor) {
10683
            toggleContentAreaOnFocus(editor, remove$7);
10684
          }
10685
          if (!isUIElement(editor, getActiveElement(editor)) && focusedEditor === editor) {
10686
            editor.dispatch('blur', { focusedEditor: null });
10687
            editorManager.focusedEditor = null;
10688
          }
10689
        });
10690
      });
10691
      if (!documentFocusInHandler) {
10692
        documentFocusInHandler = e => {
10693
          const activeEditor = editorManager.activeEditor;
10694
          if (activeEditor) {
10695
            getOriginalEventTarget(e).each(target => {
10696
              const elem = target;
10697
              if (elem.ownerDocument === document) {
10698
                if (elem !== document.body && !isUIElement(activeEditor, elem) && editorManager.focusedEditor === activeEditor) {
10699
                  activeEditor.dispatch('blur', { focusedEditor: null });
10700
                  editorManager.focusedEditor = null;
10701
                }
10702
              }
10703
            });
10704
          }
10705
        };
10706
        DOM$9.bind(document, 'focusin', documentFocusInHandler);
10707
      }
10708
    };
10709
    const unregisterDocumentEvents = (editorManager, e) => {
10710
      if (editorManager.focusedEditor === e.editor) {
10711
        editorManager.focusedEditor = null;
10712
      }
10713
      if (!editorManager.activeEditor && documentFocusInHandler) {
10714
        DOM$9.unbind(document, 'focusin', documentFocusInHandler);
10715
        documentFocusInHandler = null;
10716
      }
10717
    };
10718
    const setup$w = editorManager => {
10719
      editorManager.on('AddEditor', curry(registerEvents$1, editorManager));
10720
      editorManager.on('RemoveEditor', curry(unregisterDocumentEvents, editorManager));
10721
    };
10722
 
10723
    const getContentEditableHost = (editor, node) => editor.dom.getParent(node, node => editor.dom.getContentEditable(node) === 'true');
10724
    const getCollapsedNode = rng => rng.collapsed ? Optional.from(getNode$1(rng.startContainer, rng.startOffset)).map(SugarElement.fromDom) : Optional.none();
10725
    const getFocusInElement = (root, rng) => getCollapsedNode(rng).bind(node => {
10726
      if (isTableSection(node)) {
10727
        return Optional.some(node);
10728
      } else if (!contains(root, node)) {
10729
        return Optional.some(root);
10730
      } else {
10731
        return Optional.none();
10732
      }
10733
    });
10734
    const normalizeSelection = (editor, rng) => {
10735
      getFocusInElement(SugarElement.fromDom(editor.getBody()), rng).bind(elm => {
10736
        return firstPositionIn(elm.dom);
10737
      }).fold(() => {
10738
        editor.selection.normalize();
10739
      }, caretPos => editor.selection.setRng(caretPos.toRange()));
10740
    };
10741
    const focusBody = body => {
10742
      if (body.setActive) {
10743
        try {
10744
          body.setActive();
10745
        } catch (ex) {
10746
          body.focus();
10747
        }
10748
      } else {
10749
        body.focus();
10750
      }
10751
    };
10752
    const hasElementFocus = elm => hasFocus$1(elm) || search(elm).isSome();
10753
    const hasIframeFocus = editor => isNonNullable(editor.iframeElement) && hasFocus$1(SugarElement.fromDom(editor.iframeElement));
10754
    const hasInlineFocus = editor => {
10755
      const rawBody = editor.getBody();
10756
      return rawBody && hasElementFocus(SugarElement.fromDom(rawBody));
10757
    };
10758
    const hasUiFocus = editor => {
10759
      const dos = getRootNode(SugarElement.fromDom(editor.getElement()));
10760
      return active$1(dos).filter(elem => !isEditorContentAreaElement(elem.dom) && isUIElement(editor, elem.dom)).isSome();
10761
    };
10762
    const hasFocus = editor => editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor);
10763
    const hasEditorOrUiFocus = editor => hasFocus(editor) || hasUiFocus(editor);
10764
    const focusEditor = editor => {
10765
      const selection = editor.selection;
10766
      const body = editor.getBody();
10767
      let rng = selection.getRng();
10768
      editor.quirks.refreshContentEditable();
10769
      if (isNonNullable(editor.bookmark) && !hasFocus(editor)) {
10770
        getRng(editor).each(bookmarkRng => {
10771
          editor.selection.setRng(bookmarkRng);
10772
          rng = bookmarkRng;
10773
        });
10774
      }
10775
      const contentEditableHost = getContentEditableHost(editor, selection.getNode());
10776
      if (contentEditableHost && editor.dom.isChildOf(contentEditableHost, body)) {
10777
        focusBody(contentEditableHost);
10778
        normalizeSelection(editor, rng);
10779
        activateEditor(editor);
10780
        return;
10781
      }
10782
      if (!editor.inline) {
10783
        if (!Env.browser.isOpera()) {
10784
          focusBody(body);
10785
        }
10786
        editor.getWin().focus();
10787
      }
10788
      if (Env.browser.isFirefox() || editor.inline) {
10789
        focusBody(body);
10790
        normalizeSelection(editor, rng);
10791
      }
10792
      activateEditor(editor);
10793
    };
10794
    const activateEditor = editor => editor.editorManager.setActive(editor);
10795
    const focus = (editor, skipFocus) => {
10796
      if (editor.removed) {
10797
        return;
10798
      }
10799
      if (skipFocus) {
10800
        activateEditor(editor);
10801
      } else {
10802
        focusEditor(editor);
10803
      }
10804
    };
10805
 
10806
    const isEditableRange = (dom, rng) => {
10807
      if (rng.collapsed) {
10808
        return dom.isEditable(rng.startContainer);
10809
      } else {
10810
        return dom.isEditable(rng.startContainer) && dom.isEditable(rng.endContainer);
10811
      }
10812
    };
10813
 
10814
    const getEndpointElement = (root, rng, start, real, resolve) => {
10815
      const container = start ? rng.startContainer : rng.endContainer;
10816
      const offset = start ? rng.startOffset : rng.endOffset;
10817
      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);
10818
    };
10819
    const getStart = (root, rng, real = false) => getEndpointElement(root, rng, true, real, (elm, offset) => Math.min(childNodesCount(elm), offset));
10820
    const getEnd$1 = (root, rng, real = false) => getEndpointElement(root, rng, false, real, (elm, offset) => offset > 0 ? offset - 1 : offset);
10821
    const skipEmptyTextNodes = (node, forwards) => {
10822
      const orig = node;
10823
      while (node && isText$a(node) && node.length === 0) {
10824
        node = forwards ? node.nextSibling : node.previousSibling;
10825
      }
10826
      return node || orig;
10827
    };
10828
    const getNode = (root, rng) => {
10829
      if (!rng) {
10830
        return root;
10831
      }
10832
      let startContainer = rng.startContainer;
10833
      let endContainer = rng.endContainer;
10834
      const startOffset = rng.startOffset;
10835
      const endOffset = rng.endOffset;
10836
      let node = rng.commonAncestorContainer;
10837
      if (!rng.collapsed) {
10838
        if (startContainer === endContainer) {
10839
          if (endOffset - startOffset < 2) {
10840
            if (startContainer.hasChildNodes()) {
10841
              node = startContainer.childNodes[startOffset];
10842
            }
10843
          }
10844
        }
10845
        if (isText$a(startContainer) && isText$a(endContainer)) {
10846
          if (startContainer.length === startOffset) {
10847
            startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
10848
          } else {
10849
            startContainer = startContainer.parentNode;
10850
          }
10851
          if (endOffset === 0) {
10852
            endContainer = skipEmptyTextNodes(endContainer.previousSibling, false);
10853
          } else {
10854
            endContainer = endContainer.parentNode;
10855
          }
10856
          if (startContainer && startContainer === endContainer) {
10857
            node = startContainer;
10858
          }
10859
        }
10860
      }
10861
      const elm = isText$a(node) ? node.parentNode : node;
10862
      return isHTMLElement(elm) ? elm : root;
10863
    };
10864
    const getSelectedBlocks = (dom, rng, startElm, endElm) => {
10865
      const selectedBlocks = [];
10866
      const root = dom.getRoot();
10867
      const start = dom.getParent(startElm || getStart(root, rng, rng.collapsed), dom.isBlock);
10868
      const end = dom.getParent(endElm || getEnd$1(root, rng, rng.collapsed), dom.isBlock);
10869
      if (start && start !== root) {
10870
        selectedBlocks.push(start);
10871
      }
10872
      if (start && end && start !== end) {
10873
        let node;
10874
        const walker = new DomTreeWalker(start, root);
10875
        while ((node = walker.next()) && node !== end) {
10876
          if (dom.isBlock(node)) {
10877
            selectedBlocks.push(node);
10878
          }
10879
        }
10880
      }
10881
      if (end && start !== end && end !== root) {
10882
        selectedBlocks.push(end);
10883
      }
10884
      return selectedBlocks;
10885
    };
10886
    const select = (dom, node, content) => Optional.from(node).bind(node => Optional.from(node.parentNode).map(parent => {
10887
      const idx = dom.nodeIndex(node);
10888
      const rng = dom.createRng();
10889
      rng.setStart(parent, idx);
10890
      rng.setEnd(parent, idx + 1);
10891
      if (content) {
10892
        moveEndPoint(dom, rng, node, true);
10893
        moveEndPoint(dom, rng, node, false);
10894
      }
10895
      return rng;
10896
    }));
10897
 
10898
    const processRanges = (editor, ranges) => map$3(ranges, range => {
10899
      const evt = editor.dispatch('GetSelectionRange', { range });
10900
      return evt.range !== range ? evt.range : range;
10901
    });
10902
 
10903
    const getEnd = element => name(element) === 'img' ? 1 : getOption(element).fold(() => children$1(element).length, v => v.length);
10904
    const isTextNodeWithCursorPosition = el => getOption(el).filter(text => text.trim().length !== 0 || text.indexOf(nbsp) > -1).isSome();
10905
    const isContentEditableFalse$5 = elem => isHTMLElement$1(elem) && get$9(elem, 'contenteditable') === 'false';
10906
    const elementsWithCursorPosition = [
10907
      'img',
10908
      'br'
10909
    ];
10910
    const isCursorPosition = elem => {
10911
      const hasCursorPosition = isTextNodeWithCursorPosition(elem);
10912
      return hasCursorPosition || contains$2(elementsWithCursorPosition, name(elem)) || isContentEditableFalse$5(elem);
10913
    };
10914
 
10915
    const first = element => descendant$2(element, isCursorPosition);
10916
    const last = element => descendantRtl(element, isCursorPosition);
10917
    const descendantRtl = (scope, predicate) => {
10918
      const descend = element => {
10919
        const children = children$1(element);
10920
        for (let i = children.length - 1; i >= 0; i--) {
10921
          const child = children[i];
10922
          if (predicate(child)) {
10923
            return Optional.some(child);
10924
          }
10925
          const res = descend(child);
10926
          if (res.isSome()) {
10927
            return res;
10928
          }
10929
        }
10930
        return Optional.none();
10931
      };
10932
      return descend(scope);
10933
    };
10934
 
10935
    const autocompleteSelector = '[data-mce-autocompleter]';
10936
    const create$9 = (editor, range) => {
10937
      if (findIn(SugarElement.fromDom(editor.getBody())).isNone()) {
10938
        const wrapper = SugarElement.fromHtml('<span data-mce-autocompleter="1" data-mce-bogus="1"></span>', editor.getDoc());
10939
        append$1(wrapper, SugarElement.fromDom(range.extractContents()));
10940
        range.insertNode(wrapper.dom);
10941
        parent(wrapper).each(elm => elm.dom.normalize());
10942
        last(wrapper).map(last => {
10943
          editor.selection.setCursorLocation(last.dom, getEnd(last));
10944
        });
10945
      }
10946
    };
10947
    const detect$1 = elm => closest$3(elm, autocompleteSelector);
10948
    const findIn = elm => descendant$1(elm, autocompleteSelector);
10949
    const remove$2 = (editor, elm) => findIn(elm).each(wrapper => {
10950
      const bookmark = editor.selection.getBookmark();
10951
      unwrap(wrapper);
10952
      editor.selection.moveToBookmark(bookmark);
10953
    });
10954
 
10955
    const typeLookup = {
10956
      '#text': 3,
10957
      '#comment': 8,
10958
      '#cdata': 4,
10959
      '#pi': 7,
10960
      '#doctype': 10,
10961
      '#document-fragment': 11
10962
    };
10963
    const walk$2 = (node, root, prev) => {
10964
      const startName = prev ? 'lastChild' : 'firstChild';
10965
      const siblingName = prev ? 'prev' : 'next';
10966
      if (node[startName]) {
10967
        return node[startName];
10968
      }
10969
      if (node !== root) {
10970
        let sibling = node[siblingName];
10971
        if (sibling) {
10972
          return sibling;
10973
        }
10974
        for (let parent = node.parent; parent && parent !== root; parent = parent.parent) {
10975
          sibling = parent[siblingName];
10976
          if (sibling) {
10977
            return sibling;
10978
          }
10979
        }
10980
      }
10981
      return undefined;
10982
    };
10983
    const isEmptyTextNode = node => {
10984
      var _a;
10985
      const text = (_a = node.value) !== null && _a !== void 0 ? _a : '';
10986
      if (!isWhitespaceText(text)) {
10987
        return false;
10988
      }
10989
      const parentNode = node.parent;
10990
      if (parentNode && (parentNode.name !== 'span' || parentNode.attr('style')) && /^[ ]+$/.test(text)) {
10991
        return false;
10992
      }
10993
      return true;
10994
    };
10995
    const isNonEmptyElement = node => {
10996
      const isNamedAnchor = node.name === 'a' && !node.attr('href') && node.attr('id');
10997
      return node.attr('name') || node.attr('id') && !node.firstChild || node.attr('data-mce-bookmark') || isNamedAnchor;
10998
    };
10999
    class AstNode {
11000
      static create(name, attrs) {
11001
        const node = new AstNode(name, typeLookup[name] || 1);
11002
        if (attrs) {
11003
          each$d(attrs, (value, attrName) => {
11004
            node.attr(attrName, value);
11005
          });
11006
        }
11007
        return node;
11008
      }
11009
      constructor(name, type) {
11010
        this.name = name;
11011
        this.type = type;
11012
        if (type === 1) {
11013
          this.attributes = [];
11014
          this.attributes.map = {};
11015
        }
11016
      }
11017
      replace(node) {
11018
        const self = this;
11019
        if (node.parent) {
11020
          node.remove();
11021
        }
11022
        self.insert(node, self);
11023
        self.remove();
11024
        return self;
11025
      }
11026
      attr(name, value) {
11027
        const self = this;
11028
        if (!isString(name)) {
11029
          if (isNonNullable(name)) {
11030
            each$d(name, (value, key) => {
11031
              self.attr(key, value);
11032
            });
11033
          }
11034
          return self;
11035
        }
11036
        const attrs = self.attributes;
11037
        if (attrs) {
11038
          if (value !== undefined) {
11039
            if (value === null) {
11040
              if (name in attrs.map) {
11041
                delete attrs.map[name];
11042
                let i = attrs.length;
11043
                while (i--) {
11044
                  if (attrs[i].name === name) {
11045
                    attrs.splice(i, 1);
11046
                    return self;
11047
                  }
11048
                }
11049
              }
11050
              return self;
11051
            }
11052
            if (name in attrs.map) {
11053
              let i = attrs.length;
11054
              while (i--) {
11055
                if (attrs[i].name === name) {
11056
                  attrs[i].value = value;
11057
                  break;
11058
                }
11059
              }
11060
            } else {
11061
              attrs.push({
11062
                name,
11063
                value
11064
              });
11065
            }
11066
            attrs.map[name] = value;
11067
            return self;
11068
          }
11069
          return attrs.map[name];
11070
        }
11071
        return undefined;
11072
      }
11073
      clone() {
11074
        const self = this;
11075
        const clone = new AstNode(self.name, self.type);
11076
        const selfAttrs = self.attributes;
11077
        if (selfAttrs) {
11078
          const cloneAttrs = [];
11079
          cloneAttrs.map = {};
11080
          for (let i = 0, l = selfAttrs.length; i < l; i++) {
11081
            const selfAttr = selfAttrs[i];
11082
            if (selfAttr.name !== 'id') {
11083
              cloneAttrs[cloneAttrs.length] = {
11084
                name: selfAttr.name,
11085
                value: selfAttr.value
11086
              };
11087
              cloneAttrs.map[selfAttr.name] = selfAttr.value;
11088
            }
11089
          }
11090
          clone.attributes = cloneAttrs;
11091
        }
11092
        clone.value = self.value;
11093
        return clone;
11094
      }
11095
      wrap(wrapper) {
11096
        const self = this;
11097
        if (self.parent) {
11098
          self.parent.insert(wrapper, self);
11099
          wrapper.append(self);
11100
        }
11101
        return self;
11102
      }
11103
      unwrap() {
11104
        const self = this;
11105
        for (let node = self.firstChild; node;) {
11106
          const next = node.next;
11107
          self.insert(node, self, true);
11108
          node = next;
11109
        }
11110
        self.remove();
11111
      }
11112
      remove() {
11113
        const self = this, parent = self.parent, next = self.next, prev = self.prev;
11114
        if (parent) {
11115
          if (parent.firstChild === self) {
11116
            parent.firstChild = next;
11117
            if (next) {
11118
              next.prev = null;
11119
            }
11120
          } else if (prev) {
11121
            prev.next = next;
11122
          }
11123
          if (parent.lastChild === self) {
11124
            parent.lastChild = prev;
11125
            if (prev) {
11126
              prev.next = null;
11127
            }
11128
          } else if (next) {
11129
            next.prev = prev;
11130
          }
11131
          self.parent = self.next = self.prev = null;
11132
        }
11133
        return self;
11134
      }
11135
      append(node) {
11136
        const self = this;
11137
        if (node.parent) {
11138
          node.remove();
11139
        }
11140
        const last = self.lastChild;
11141
        if (last) {
11142
          last.next = node;
11143
          node.prev = last;
11144
          self.lastChild = node;
11145
        } else {
11146
          self.lastChild = self.firstChild = node;
11147
        }
11148
        node.parent = self;
11149
        return node;
11150
      }
11151
      insert(node, refNode, before) {
11152
        if (node.parent) {
11153
          node.remove();
11154
        }
11155
        const parent = refNode.parent || this;
11156
        if (before) {
11157
          if (refNode === parent.firstChild) {
11158
            parent.firstChild = node;
11159
          } else if (refNode.prev) {
11160
            refNode.prev.next = node;
11161
          }
11162
          node.prev = refNode.prev;
11163
          node.next = refNode;
11164
          refNode.prev = node;
11165
        } else {
11166
          if (refNode === parent.lastChild) {
11167
            parent.lastChild = node;
11168
          } else if (refNode.next) {
11169
            refNode.next.prev = node;
11170
          }
11171
          node.next = refNode.next;
11172
          node.prev = refNode;
11173
          refNode.next = node;
11174
        }
11175
        node.parent = parent;
11176
        return node;
11177
      }
11178
      getAll(name) {
11179
        const self = this;
11180
        const collection = [];
11181
        for (let node = self.firstChild; node; node = walk$2(node, self)) {
11182
          if (node.name === name) {
11183
            collection.push(node);
11184
          }
11185
        }
11186
        return collection;
11187
      }
11188
      children() {
11189
        const self = this;
11190
        const collection = [];
11191
        for (let node = self.firstChild; node; node = node.next) {
11192
          collection.push(node);
11193
        }
11194
        return collection;
11195
      }
11196
      empty() {
11197
        const self = this;
11198
        if (self.firstChild) {
11199
          const nodes = [];
11200
          for (let node = self.firstChild; node; node = walk$2(node, self)) {
11201
            nodes.push(node);
11202
          }
11203
          let i = nodes.length;
11204
          while (i--) {
11205
            const node = nodes[i];
11206
            node.parent = node.firstChild = node.lastChild = node.next = node.prev = null;
11207
          }
11208
        }
11209
        self.firstChild = self.lastChild = null;
11210
        return self;
11211
      }
11212
      isEmpty(elements, whitespace = {}, predicate) {
11213
        var _a;
11214
        const self = this;
11215
        let node = self.firstChild;
11216
        if (isNonEmptyElement(self)) {
11217
          return false;
11218
        }
11219
        if (node) {
11220
          do {
11221
            if (node.type === 1) {
11222
              if (node.attr('data-mce-bogus')) {
11223
                continue;
11224
              }
11225
              if (elements[node.name]) {
11226
                return false;
11227
              }
11228
              if (isNonEmptyElement(node)) {
11229
                return false;
11230
              }
11231
            }
11232
            if (node.type === 8) {
11233
              return false;
11234
            }
11235
            if (node.type === 3 && !isEmptyTextNode(node)) {
11236
              return false;
11237
            }
11238
            if (node.type === 3 && node.parent && whitespace[node.parent.name] && isWhitespaceText((_a = node.value) !== null && _a !== void 0 ? _a : '')) {
11239
              return false;
11240
            }
11241
            if (predicate && predicate(node)) {
11242
              return false;
11243
            }
11244
          } while (node = walk$2(node, self));
11245
        }
11246
        return true;
11247
      }
11248
      walk(prev) {
11249
        return walk$2(this, null, prev);
11250
      }
11251
    }
11252
 
11253
    const unescapedTextParents = Tools.makeMap('NOSCRIPT STYLE SCRIPT XMP IFRAME NOEMBED NOFRAMES PLAINTEXT', ' ');
11254
    const containsZwsp = node => isString(node.nodeValue) && node.nodeValue.includes(ZWSP$1);
11255
    const getTemporaryNodeSelector = tempAttrs => `${ tempAttrs.length === 0 ? '' : `${ map$3(tempAttrs, attr => `[${ attr }]`).join(',') },` }[data-mce-bogus="all"]`;
11256
    const getTemporaryNodes = (tempAttrs, body) => body.querySelectorAll(getTemporaryNodeSelector(tempAttrs));
11257
    const createZwspCommentWalker = body => document.createTreeWalker(body, NodeFilter.SHOW_COMMENT, node => containsZwsp(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP);
11258
    const createUnescapedZwspTextWalker = body => document.createTreeWalker(body, NodeFilter.SHOW_TEXT, node => {
11259
      if (containsZwsp(node)) {
11260
        const parent = node.parentNode;
11261
        return parent && has$2(unescapedTextParents, parent.nodeName) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
11262
      } else {
11263
        return NodeFilter.FILTER_SKIP;
11264
      }
11265
    });
11266
    const hasZwspComment = body => createZwspCommentWalker(body).nextNode() !== null;
11267
    const hasUnescapedZwspText = body => createUnescapedZwspTextWalker(body).nextNode() !== null;
11268
    const hasTemporaryNode = (tempAttrs, body) => body.querySelector(getTemporaryNodeSelector(tempAttrs)) !== null;
11269
    const trimTemporaryNodes = (tempAttrs, body) => {
11270
      each$e(getTemporaryNodes(tempAttrs, body), elm => {
11271
        const element = SugarElement.fromDom(elm);
11272
        if (get$9(element, 'data-mce-bogus') === 'all') {
11273
          remove$5(element);
11274
        } else {
11275
          each$e(tempAttrs, attr => {
11276
            if (has$1(element, attr)) {
11277
              remove$a(element, attr);
11278
            }
11279
          });
11280
        }
11281
      });
11282
    };
11283
    const emptyAllNodeValuesInWalker = walker => {
11284
      let curr = walker.nextNode();
11285
      while (curr !== null) {
11286
        curr.nodeValue = null;
11287
        curr = walker.nextNode();
11288
      }
11289
    };
11290
    const emptyZwspComments = compose(emptyAllNodeValuesInWalker, createZwspCommentWalker);
11291
    const emptyUnescapedZwspTexts = compose(emptyAllNodeValuesInWalker, createUnescapedZwspTextWalker);
11292
    const trim$1 = (body, tempAttrs) => {
11293
      const conditionalTrims = [
11294
        {
11295
          condition: curry(hasTemporaryNode, tempAttrs),
11296
          action: curry(trimTemporaryNodes, tempAttrs)
11297
        },
11298
        {
11299
          condition: hasZwspComment,
11300
          action: emptyZwspComments
11301
        },
11302
        {
11303
          condition: hasUnescapedZwspText,
11304
          action: emptyUnescapedZwspTexts
11305
        }
11306
      ];
11307
      let trimmed = body;
11308
      let cloned = false;
11309
      each$e(conditionalTrims, ({condition, action}) => {
11310
        if (condition(trimmed)) {
11311
          if (!cloned) {
11312
            trimmed = body.cloneNode(true);
11313
            cloned = true;
11314
          }
11315
          action(trimmed);
11316
        }
11317
      });
11318
      return trimmed;
11319
    };
11320
 
11321
    const cleanupBogusElements = parent => {
11322
      const bogusElements = descendants(parent, '[data-mce-bogus]');
11323
      each$e(bogusElements, elem => {
11324
        const bogusValue = get$9(elem, 'data-mce-bogus');
11325
        if (bogusValue === 'all') {
11326
          remove$5(elem);
11327
        } else if (isBr$5(elem)) {
11328
          before$3(elem, SugarElement.fromText(zeroWidth));
11329
          remove$5(elem);
11330
        } else {
11331
          unwrap(elem);
11332
        }
11333
      });
11334
    };
11335
    const cleanupInputNames = parent => {
11336
      const inputs = descendants(parent, 'input');
11337
      each$e(inputs, input => {
11338
        remove$a(input, 'name');
11339
      });
11340
    };
11341
 
11342
    const trimEmptyContents = (editor, html) => {
11343
      const blockName = getForcedRootBlock(editor);
11344
      const emptyRegExp = new RegExp(`^(<${ blockName }[^>]*>(&nbsp;|&#160;|\\s|\u00a0|<br \\/>|)<\\/${ blockName }>[\r\n]*|<br \\/>[\r\n]*)$`);
11345
      return html.replace(emptyRegExp, '');
11346
    };
11347
    const getPlainTextContent = (editor, body) => {
11348
      const doc = editor.getDoc();
11349
      const dos = getRootNode(SugarElement.fromDom(editor.getBody()));
11350
      const offscreenDiv = SugarElement.fromTag('div', doc);
11351
      set$3(offscreenDiv, 'data-mce-bogus', 'all');
11352
      setAll(offscreenDiv, {
11353
        position: 'fixed',
11354
        left: '-9999999px',
11355
        top: '0'
11356
      });
11357
      set$1(offscreenDiv, body.innerHTML);
11358
      cleanupBogusElements(offscreenDiv);
11359
      cleanupInputNames(offscreenDiv);
11360
      const root = getContentContainer(dos);
11361
      append$1(root, offscreenDiv);
11362
      const content = trim$2(offscreenDiv.dom.innerText);
11363
      remove$5(offscreenDiv);
11364
      return content;
11365
    };
11366
    const getContentFromBody = (editor, args, body) => {
11367
      let content;
11368
      if (args.format === 'raw') {
11369
        content = Tools.trim(trim$2(trim$1(body, editor.serializer.getTempAttrs()).innerHTML));
11370
      } else if (args.format === 'text') {
11371
        content = getPlainTextContent(editor, body);
11372
      } else if (args.format === 'tree') {
11373
        content = editor.serializer.serialize(body, args);
11374
      } else {
11375
        content = trimEmptyContents(editor, editor.serializer.serialize(body, args));
11376
      }
11377
      const shouldTrim = args.format !== 'text' && !isWsPreserveElement(SugarElement.fromDom(body));
11378
      return shouldTrim && isString(content) ? Tools.trim(content) : content;
11379
    };
11380
    const getContentInternal = (editor, args) => Optional.from(editor.getBody()).fold(constant(args.format === 'tree' ? new AstNode('body', 11) : ''), body => getContentFromBody(editor, args, body));
11381
 
11382
    const makeMap$1 = Tools.makeMap;
11383
    const Writer = settings => {
11384
      const html = [];
11385
      settings = settings || {};
11386
      const indent = settings.indent;
11387
      const indentBefore = makeMap$1(settings.indent_before || '');
11388
      const indentAfter = makeMap$1(settings.indent_after || '');
11389
      const encode = Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities);
11390
      const htmlOutput = settings.element_format !== 'xhtml';
11391
      return {
11392
        start: (name, attrs, empty) => {
11393
          if (indent && indentBefore[name] && html.length > 0) {
11394
            const value = html[html.length - 1];
11395
            if (value.length > 0 && value !== '\n') {
11396
              html.push('\n');
11397
            }
11398
          }
11399
          html.push('<', name);
11400
          if (attrs) {
11401
            for (let i = 0, l = attrs.length; i < l; i++) {
11402
              const attr = attrs[i];
11403
              html.push(' ', attr.name, '="', encode(attr.value, true), '"');
11404
            }
11405
          }
11406
          if (!empty || htmlOutput) {
11407
            html[html.length] = '>';
11408
          } else {
11409
            html[html.length] = ' />';
11410
          }
11411
          if (empty && indent && indentAfter[name] && html.length > 0) {
11412
            const value = html[html.length - 1];
11413
            if (value.length > 0 && value !== '\n') {
11414
              html.push('\n');
11415
            }
11416
          }
11417
        },
11418
        end: name => {
11419
          let value;
11420
          html.push('</', name, '>');
11421
          if (indent && indentAfter[name] && html.length > 0) {
11422
            value = html[html.length - 1];
11423
            if (value.length > 0 && value !== '\n') {
11424
              html.push('\n');
11425
            }
11426
          }
11427
        },
11428
        text: (text, raw) => {
11429
          if (text.length > 0) {
11430
            html[html.length] = raw ? text : encode(text);
11431
          }
11432
        },
11433
        cdata: text => {
11434
          html.push('<![CDATA[', text, ']]>');
11435
        },
11436
        comment: text => {
11437
          html.push('<!--', text, '-->');
11438
        },
11439
        pi: (name, text) => {
11440
          if (text) {
11441
            html.push('<?', name, ' ', encode(text), '?>');
11442
          } else {
11443
            html.push('<?', name, '?>');
11444
          }
11445
          if (indent) {
11446
            html.push('\n');
11447
          }
11448
        },
11449
        doctype: text => {
11450
          html.push('<!DOCTYPE', text, '>', indent ? '\n' : '');
11451
        },
11452
        reset: () => {
11453
          html.length = 0;
11454
        },
11455
        getContent: () => {
11456
          return html.join('').replace(/\n$/, '');
11457
        }
11458
      };
11459
    };
11460
 
11461
    const HtmlSerializer = (settings = {}, schema = Schema()) => {
11462
      const writer = Writer(settings);
11463
      settings.validate = 'validate' in settings ? settings.validate : true;
11464
      const serialize = node => {
11465
        const validate = settings.validate;
11466
        const handlers = {
11467
          3: node => {
11468
            var _a;
11469
            writer.text((_a = node.value) !== null && _a !== void 0 ? _a : '', node.raw);
11470
          },
11471
          8: node => {
11472
            var _a;
11473
            writer.comment((_a = node.value) !== null && _a !== void 0 ? _a : '');
11474
          },
11475
          7: node => {
11476
            writer.pi(node.name, node.value);
11477
          },
11478
          10: node => {
11479
            var _a;
11480
            writer.doctype((_a = node.value) !== null && _a !== void 0 ? _a : '');
11481
          },
11482
          4: node => {
11483
            var _a;
11484
            writer.cdata((_a = node.value) !== null && _a !== void 0 ? _a : '');
11485
          },
11486
          11: node => {
11487
            let tempNode = node;
11488
            if (tempNode = tempNode.firstChild) {
11489
              do {
11490
                walk(tempNode);
11491
              } while (tempNode = tempNode.next);
11492
            }
11493
          }
11494
        };
11495
        writer.reset();
11496
        const walk = node => {
11497
          var _a;
11498
          const handler = handlers[node.type];
11499
          if (!handler) {
11500
            const name = node.name;
11501
            const isEmpty = name in schema.getVoidElements();
11502
            let attrs = node.attributes;
11503
            if (validate && attrs && attrs.length > 1) {
11504
              const sortedAttrs = [];
11505
              sortedAttrs.map = {};
11506
              const elementRule = schema.getElementRule(node.name);
11507
              if (elementRule) {
11508
                for (let i = 0, l = elementRule.attributesOrder.length; i < l; i++) {
11509
                  const attrName = elementRule.attributesOrder[i];
11510
                  if (attrName in attrs.map) {
11511
                    const attrValue = attrs.map[attrName];
11512
                    sortedAttrs.map[attrName] = attrValue;
11513
                    sortedAttrs.push({
11514
                      name: attrName,
11515
                      value: attrValue
11516
                    });
11517
                  }
11518
                }
11519
                for (let i = 0, l = attrs.length; i < l; i++) {
11520
                  const attrName = attrs[i].name;
11521
                  if (!(attrName in sortedAttrs.map)) {
11522
                    const attrValue = attrs.map[attrName];
11523
                    sortedAttrs.map[attrName] = attrValue;
11524
                    sortedAttrs.push({
11525
                      name: attrName,
11526
                      value: attrValue
11527
                    });
11528
                  }
11529
                }
11530
                attrs = sortedAttrs;
11531
              }
11532
            }
11533
            writer.start(name, attrs, isEmpty);
11534
            if (isNonHtmlElementRootName(name)) {
11535
              if (isString(node.value)) {
11536
                writer.text(node.value, true);
11537
              }
11538
              writer.end(name);
11539
            } else {
11540
              if (!isEmpty) {
11541
                let child = node.firstChild;
11542
                if (child) {
11543
                  if ((name === 'pre' || name === 'textarea') && child.type === 3 && ((_a = child.value) === null || _a === void 0 ? void 0 : _a[0]) === '\n') {
11544
                    writer.text('\n', true);
11545
                  }
11546
                  do {
11547
                    walk(child);
11548
                  } while (child = child.next);
11549
                }
11550
                writer.end(name);
11551
              }
11552
            }
11553
          } else {
11554
            handler(node);
11555
          }
11556
        };
11557
        if (node.type === 1 && !settings.inner) {
11558
          walk(node);
11559
        } else if (node.type === 3) {
11560
          handlers[3](node);
11561
        } else {
11562
          handlers[11](node);
11563
        }
11564
        return writer.getContent();
11565
      };
11566
      return { serialize };
11567
    };
11568
 
11569
    const nonInheritableStyles = new Set();
11570
    (() => {
11571
      const nonInheritableStylesArr = [
11572
        'margin',
11573
        'margin-left',
11574
        'margin-right',
11575
        'margin-top',
11576
        'margin-bottom',
11577
        'padding',
11578
        'padding-left',
11579
        'padding-right',
11580
        'padding-top',
11581
        'padding-bottom',
11582
        'border',
11583
        'border-width',
11584
        'border-style',
11585
        'border-color',
11586
        'background',
11587
        'background-attachment',
11588
        'background-clip',
11589
        'background-color',
11590
        'background-image',
11591
        'background-origin',
11592
        'background-position',
11593
        'background-repeat',
11594
        'background-size',
11595
        'float',
11596
        'position',
11597
        'left',
11598
        'right',
11599
        'top',
11600
        'bottom',
11601
        'z-index',
11602
        'display',
11603
        'transform',
11604
        'width',
11605
        'max-width',
11606
        'min-width',
11607
        'height',
11608
        'max-height',
11609
        'min-height',
11610
        'overflow',
11611
        'overflow-x',
11612
        'overflow-y',
11613
        'text-overflow',
11614
        'vertical-align',
11615
        'transition',
11616
        'transition-delay',
11617
        'transition-duration',
11618
        'transition-property',
11619
        'transition-timing-function'
11620
      ];
11621
      each$e(nonInheritableStylesArr, style => {
11622
        nonInheritableStyles.add(style);
11623
      });
11624
    })();
11625
    const shorthandStyleProps = [
11626
      'font',
11627
      'text-decoration',
11628
      'text-emphasis'
11629
    ];
11630
    const getStyleProps = (dom, node) => keys(dom.parseStyle(dom.getAttrib(node, 'style')));
11631
    const isNonInheritableStyle = style => nonInheritableStyles.has(style);
11632
    const hasInheritableStyles = (dom, node) => forall(getStyleProps(dom, node), style => !isNonInheritableStyle(style));
11633
    const getLonghandStyleProps = styles => filter$5(styles, style => exists(shorthandStyleProps, prop => startsWith(style, prop)));
11634
    const hasStyleConflict = (dom, node, parentNode) => {
11635
      const nodeStyleProps = getStyleProps(dom, node);
11636
      const parentNodeStyleProps = getStyleProps(dom, parentNode);
11637
      const valueMismatch = prop => {
11638
        var _a, _b;
11639
        const nodeValue = (_a = dom.getStyle(node, prop)) !== null && _a !== void 0 ? _a : '';
11640
        const parentValue = (_b = dom.getStyle(parentNode, prop)) !== null && _b !== void 0 ? _b : '';
11641
        return isNotEmpty(nodeValue) && isNotEmpty(parentValue) && nodeValue !== parentValue;
11642
      };
11643
      return exists(nodeStyleProps, nodeStyleProp => {
11644
        const propExists = props => exists(props, prop => prop === nodeStyleProp);
11645
        if (!propExists(parentNodeStyleProps) && propExists(shorthandStyleProps)) {
11646
          const longhandProps = getLonghandStyleProps(parentNodeStyleProps);
11647
          return exists(longhandProps, valueMismatch);
11648
        } else {
11649
          return valueMismatch(nodeStyleProp);
11650
        }
11651
      });
11652
    };
11653
 
11654
    const isChar = (forward, predicate, pos) => Optional.from(pos.container()).filter(isText$a).exists(text => {
11655
      const delta = forward ? 0 : -1;
11656
      return predicate(text.data.charAt(pos.offset() + delta));
11657
    });
11658
    const isBeforeSpace = curry(isChar, true, isWhiteSpace);
11659
    const isAfterSpace = curry(isChar, false, isWhiteSpace);
11660
    const isEmptyText = pos => {
11661
      const container = pos.container();
11662
      return isText$a(container) && (container.data.length === 0 || isZwsp$1(container.data) && BookmarkManager.isBookmarkNode(container.parentNode));
11663
    };
11664
    const matchesElementPosition = (before, predicate) => pos => getChildNodeAtRelativeOffset(before ? 0 : -1, pos).filter(predicate).isSome();
11665
    const isImageBlock = node => isImg(node) && get$7(SugarElement.fromDom(node), 'display') === 'block';
11666
    const isCefNode = node => isContentEditableFalse$b(node) && !isBogusAll$1(node);
11667
    const isBeforeImageBlock = matchesElementPosition(true, isImageBlock);
11668
    const isAfterImageBlock = matchesElementPosition(false, isImageBlock);
11669
    const isBeforeMedia = matchesElementPosition(true, isMedia$2);
11670
    const isAfterMedia = matchesElementPosition(false, isMedia$2);
11671
    const isBeforeTable = matchesElementPosition(true, isTable$2);
11672
    const isAfterTable = matchesElementPosition(false, isTable$2);
11673
    const isBeforeContentEditableFalse = matchesElementPosition(true, isCefNode);
11674
    const isAfterContentEditableFalse = matchesElementPosition(false, isCefNode);
11675
 
11676
    const dropLast = xs => xs.slice(0, -1);
11677
    const parentsUntil = (start, root, predicate) => {
11678
      if (contains(root, start)) {
11679
        return dropLast(parents$1(start, elm => {
11680
          return predicate(elm) || eq(elm, root);
11681
        }));
11682
      } else {
11683
        return [];
11684
      }
11685
    };
11686
    const parents = (start, root) => parentsUntil(start, root, never);
11687
    const parentsAndSelf = (start, root) => [start].concat(parents(start, root));
11688
 
11689
    const navigateIgnoreEmptyTextNodes = (forward, root, from) => navigateIgnore(forward, root, from, isEmptyText);
11690
    const isBlock$1 = schema => el => schema.isBlock(name(el));
11691
    const getClosestBlock$1 = (root, pos, schema) => find$2(parentsAndSelf(SugarElement.fromDom(pos.container()), root), isBlock$1(schema));
11692
    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()))));
11693
    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());
11694
    const isAtStartOfBlock = curry(isAtBlockBoundary, false);
11695
    const isAtEndOfBlock = curry(isAtBlockBoundary, true);
11696
    const isBeforeBlock = curry(isAtBeforeAfterBlockBoundary, false);
11697
    const isAfterBlock = curry(isAtBeforeAfterBlockBoundary, true);
11698
 
11699
    const isBr$1 = pos => getElementFromPosition(pos).exists(isBr$5);
11700
    const findBr = (forward, root, pos, schema) => {
11701
      const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), el => schema.isBlock(name(el)));
11702
      const scope = head(parentBlocks).getOr(root);
11703
      return fromPosition(forward, scope.dom, pos).filter(isBr$1);
11704
    };
11705
    const isBeforeBr$1 = (root, pos, schema) => getElementFromPosition(pos).exists(isBr$5) || findBr(true, root, pos, schema).isSome();
11706
    const isAfterBr = (root, pos, schema) => getElementFromPrevPosition(pos).exists(isBr$5) || findBr(false, root, pos, schema).isSome();
11707
    const findPreviousBr = curry(findBr, false);
11708
    const findNextBr = curry(findBr, true);
11709
 
11710
    const isInMiddleOfText = pos => CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd();
11711
    const getClosestBlock = (root, pos, schema) => {
11712
      const parentBlocks = filter$5(parentsAndSelf(SugarElement.fromDom(pos.container()), root), el => schema.isBlock(name(el)));
11713
      return head(parentBlocks).getOr(root);
11714
    };
11715
    const hasSpaceBefore = (root, pos, schema) => {
11716
      if (isInMiddleOfText(pos)) {
11717
        return isAfterSpace(pos);
11718
      } else {
11719
        return isAfterSpace(pos) || prevPosition(getClosestBlock(root, pos, schema).dom, pos).exists(isAfterSpace);
11720
      }
11721
    };
11722
    const hasSpaceAfter = (root, pos, schema) => {
11723
      if (isInMiddleOfText(pos)) {
11724
        return isBeforeSpace(pos);
11725
      } else {
11726
        return isBeforeSpace(pos) || nextPosition(getClosestBlock(root, pos, schema).dom, pos).exists(isBeforeSpace);
11727
      }
11728
    };
11729
    const isPreValue = value => contains$2([
11730
      'pre',
11731
      'pre-wrap'
11732
    ], value);
11733
    const isInPre = pos => getElementFromPosition(pos).bind(elm => closest$4(elm, isElement$7)).exists(elm => isPreValue(get$7(elm, 'white-space')));
11734
    const isAtBeginningOfBody = (root, pos) => prevPosition(root.dom, pos).isNone();
11735
    const isAtEndOfBody = (root, pos) => nextPosition(root.dom, pos).isNone();
11736
    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);
11737
    const isCefBlock = node => isNonNullable(node) && isContentEditableFalse$b(node) && isBlockLike(node);
11738
    const isSiblingCefBlock = (root, direction) => container => {
11739
      return isCefBlock(new DomTreeWalker(container, root)[direction]());
11740
    };
11741
    const isBeforeCefBlock = (root, pos) => {
11742
      const nextPos = nextPosition(root.dom, pos).getOr(pos);
11743
      const isNextCefBlock = isSiblingCefBlock(root.dom, 'next');
11744
      return pos.isAtEnd() && (isNextCefBlock(pos.container()) || isNextCefBlock(nextPos.container()));
11745
    };
11746
    const isAfterCefBlock = (root, pos) => {
11747
      const prevPos = prevPosition(root.dom, pos).getOr(pos);
11748
      const isPrevCefBlock = isSiblingCefBlock(root.dom, 'prev');
11749
      return pos.isAtStart() && (isPrevCefBlock(pos.container()) || isPrevCefBlock(prevPos.container()));
11750
    };
11751
    const needsToHaveNbsp = (root, pos, schema) => {
11752
      if (isInPre(pos)) {
11753
        return false;
11754
      } else {
11755
        return isAtLineBoundary(root, pos, schema) || hasSpaceBefore(root, pos, schema) || hasSpaceAfter(root, pos, schema);
11756
      }
11757
    };
11758
    const needsToBeNbspLeft = (root, pos, schema) => {
11759
      if (isInPre(pos)) {
11760
        return false;
11761
      } else {
11762
        return isAtStartOfBlock(root, pos, schema) || isBeforeBlock(root, pos, schema) || isAfterBr(root, pos, schema) || hasSpaceBefore(root, pos, schema) || isAfterCefBlock(root, pos);
11763
      }
11764
    };
11765
    const leanRight = pos => {
11766
      const container = pos.container();
11767
      const offset = pos.offset();
11768
      if (isText$a(container) && offset < container.data.length) {
11769
        return CaretPosition(container, offset + 1);
11770
      } else {
11771
        return pos;
11772
      }
11773
    };
11774
    const needsToBeNbspRight = (root, pos, schema) => {
11775
      if (isInPre(pos)) {
11776
        return false;
11777
      } else {
11778
        return isAtEndOfBlock(root, pos, schema) || isAfterBlock(root, pos, schema) || isBeforeBr$1(root, pos, schema) || hasSpaceAfter(root, pos, schema) || isBeforeCefBlock(root, pos);
11779
      }
11780
    };
11781
    const needsToBeNbsp = (root, pos, schema) => needsToBeNbspLeft(root, pos, schema) || needsToBeNbspRight(root, leanRight(pos), schema);
11782
    const isNbspAt = (text, offset) => isNbsp(text.charAt(offset));
11783
    const isWhiteSpaceAt = (text, offset) => isWhiteSpace(text.charAt(offset));
11784
    const hasNbsp = pos => {
11785
      const container = pos.container();
11786
      return isText$a(container) && contains$1(container.data, nbsp);
11787
    };
11788
    const normalizeNbspMiddle = text => {
11789
      const chars = text.split('');
11790
      return map$3(chars, (chr, i) => {
11791
        if (isNbsp(chr) && i > 0 && i < chars.length - 1 && isContent(chars[i - 1]) && isContent(chars[i + 1])) {
11792
          return ' ';
11793
        } else {
11794
          return chr;
11795
        }
11796
      }).join('');
11797
    };
11798
    const normalizeNbspAtStart = (root, node, makeNbsp, schema) => {
11799
      const text = node.data;
11800
      const firstPos = CaretPosition(node, 0);
11801
      if (!makeNbsp && isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos, schema)) {
11802
        node.data = ' ' + text.slice(1);
11803
        return true;
11804
      } else if (makeNbsp && isWhiteSpaceAt(text, 0) && needsToBeNbspLeft(root, firstPos, schema)) {
11805
        node.data = nbsp + text.slice(1);
11806
        return true;
11807
      } else {
11808
        return false;
11809
      }
11810
    };
11811
    const normalizeNbspInMiddleOfTextNode = node => {
11812
      const text = node.data;
11813
      const newText = normalizeNbspMiddle(text);
11814
      if (newText !== text) {
11815
        node.data = newText;
11816
        return true;
11817
      } else {
11818
        return false;
11819
      }
11820
    };
11821
    const normalizeNbspAtEnd = (root, node, makeNbsp, schema) => {
11822
      const text = node.data;
11823
      const lastPos = CaretPosition(node, text.length - 1);
11824
      if (!makeNbsp && isNbspAt(text, text.length - 1) && !needsToBeNbsp(root, lastPos, schema)) {
11825
        node.data = text.slice(0, -1) + ' ';
11826
        return true;
11827
      } else if (makeNbsp && isWhiteSpaceAt(text, text.length - 1) && needsToBeNbspRight(root, lastPos, schema)) {
11828
        node.data = text.slice(0, -1) + nbsp;
11829
        return true;
11830
      } else {
11831
        return false;
11832
      }
11833
    };
11834
    const normalizeNbsps = (root, pos, schema) => {
11835
      const container = pos.container();
11836
      if (!isText$a(container)) {
11837
        return Optional.none();
11838
      }
11839
      if (hasNbsp(pos)) {
11840
        const normalized = normalizeNbspAtStart(root, container, false, schema) || normalizeNbspInMiddleOfTextNode(container) || normalizeNbspAtEnd(root, container, false, schema);
11841
        return someIf(normalized, pos);
11842
      } else if (needsToBeNbsp(root, pos, schema)) {
11843
        const normalized = normalizeNbspAtStart(root, container, true, schema) || normalizeNbspAtEnd(root, container, true, schema);
11844
        return someIf(normalized, pos);
11845
      } else {
11846
        return Optional.none();
11847
      }
11848
    };
11849
    const normalizeNbspsInEditor = editor => {
11850
      const root = SugarElement.fromDom(editor.getBody());
11851
      if (editor.selection.isCollapsed()) {
11852
        normalizeNbsps(root, CaretPosition.fromRangeStart(editor.selection.getRng()), editor.schema).each(pos => {
11853
          editor.selection.setRng(pos.toRange());
11854
        });
11855
      }
11856
    };
11857
 
11858
    const normalize$1 = (node, offset, count, schema) => {
11859
      if (count === 0) {
11860
        return;
11861
      }
11862
      const elm = SugarElement.fromDom(node);
11863
      const root = ancestor$4(elm, el => schema.isBlock(name(el))).getOr(elm);
11864
      const whitespace = node.data.slice(offset, offset + count);
11865
      const isEndOfContent = offset + count >= node.data.length && needsToBeNbspRight(root, CaretPosition(node, node.data.length), schema);
11866
      const isStartOfContent = offset === 0 && needsToBeNbspLeft(root, CaretPosition(node, 0), schema);
11867
      node.replaceData(offset, count, normalize$4(whitespace, 4, isStartOfContent, isEndOfContent));
11868
    };
11869
    const normalizeWhitespaceAfter = (node, offset, schema) => {
11870
      const content = node.data.slice(offset);
11871
      const whitespaceCount = content.length - lTrim(content).length;
11872
      normalize$1(node, offset, whitespaceCount, schema);
11873
    };
11874
    const normalizeWhitespaceBefore = (node, offset, schema) => {
11875
      const content = node.data.slice(0, offset);
11876
      const whitespaceCount = content.length - rTrim(content).length;
11877
      normalize$1(node, offset - whitespaceCount, whitespaceCount, schema);
11878
    };
11879
    const mergeTextNodes = (prevNode, nextNode, schema, normalizeWhitespace, mergeToPrev = true) => {
11880
      const whitespaceOffset = rTrim(prevNode.data).length;
11881
      const newNode = mergeToPrev ? prevNode : nextNode;
11882
      const removeNode = mergeToPrev ? nextNode : prevNode;
11883
      if (mergeToPrev) {
11884
        newNode.appendData(removeNode.data);
11885
      } else {
11886
        newNode.insertData(0, removeNode.data);
11887
      }
11888
      remove$5(SugarElement.fromDom(removeNode));
11889
      if (normalizeWhitespace) {
11890
        normalizeWhitespaceAfter(newNode, whitespaceOffset, schema);
11891
      }
11892
      return newNode;
11893
    };
11894
 
11895
    const needsReposition = (pos, elm) => {
11896
      const container = pos.container();
11897
      const offset = pos.offset();
11898
      return !CaretPosition.isTextPosition(pos) && container === elm.parentNode && offset > CaretPosition.before(elm).offset();
11899
    };
11900
    const reposition = (elm, pos) => needsReposition(pos, elm) ? CaretPosition(pos.container(), pos.offset() - 1) : pos;
11901
    const beforeOrStartOf = node => isText$a(node) ? CaretPosition(node, 0) : CaretPosition.before(node);
11902
    const afterOrEndOf = node => isText$a(node) ? CaretPosition(node, node.data.length) : CaretPosition.after(node);
11903
    const getPreviousSiblingCaretPosition = elm => {
11904
      if (isCaretCandidate$3(elm.previousSibling)) {
11905
        return Optional.some(afterOrEndOf(elm.previousSibling));
11906
      } else {
11907
        return elm.previousSibling ? lastPositionIn(elm.previousSibling) : Optional.none();
11908
      }
11909
    };
11910
    const getNextSiblingCaretPosition = elm => {
11911
      if (isCaretCandidate$3(elm.nextSibling)) {
11912
        return Optional.some(beforeOrStartOf(elm.nextSibling));
11913
      } else {
11914
        return elm.nextSibling ? firstPositionIn(elm.nextSibling) : Optional.none();
11915
      }
11916
    };
11917
    const findCaretPositionBackwardsFromElm = (rootElement, elm) => {
11918
      return Optional.from(elm.previousSibling ? elm.previousSibling : elm.parentNode).bind(node => prevPosition(rootElement, CaretPosition.before(node))).orThunk(() => nextPosition(rootElement, CaretPosition.after(elm)));
11919
    };
11920
    const findCaretPositionForwardsFromElm = (rootElement, elm) => nextPosition(rootElement, CaretPosition.after(elm)).orThunk(() => prevPosition(rootElement, CaretPosition.before(elm)));
11921
    const findCaretPositionBackwards = (rootElement, elm) => getPreviousSiblingCaretPosition(elm).orThunk(() => getNextSiblingCaretPosition(elm)).orThunk(() => findCaretPositionBackwardsFromElm(rootElement, elm));
11922
    const findCaretPositionForward = (rootElement, elm) => getNextSiblingCaretPosition(elm).orThunk(() => getPreviousSiblingCaretPosition(elm)).orThunk(() => findCaretPositionForwardsFromElm(rootElement, elm));
11923
    const findCaretPosition = (forward, rootElement, elm) => forward ? findCaretPositionForward(rootElement, elm) : findCaretPositionBackwards(rootElement, elm);
11924
    const findCaretPosOutsideElmAfterDelete = (forward, rootElement, elm) => findCaretPosition(forward, rootElement, elm).map(curry(reposition, elm));
11925
    const setSelection$1 = (editor, forward, pos) => {
11926
      pos.fold(() => {
11927
        editor.focus();
11928
      }, pos => {
11929
        editor.selection.setRng(pos.toRange(), forward);
11930
      });
11931
    };
11932
    const eqRawNode = rawNode => elm => elm.dom === rawNode;
11933
    const isBlock = (editor, elm) => elm && has$2(editor.schema.getBlockElements(), name(elm));
11934
    const paddEmptyBlock = (elm, preserveEmptyCaret) => {
11935
      if (isEmpty$2(elm)) {
11936
        const br = SugarElement.fromHtml('<br data-mce-bogus="1">');
11937
        if (preserveEmptyCaret) {
11938
          each$e(children$1(elm), node => {
11939
            if (!isEmptyCaretFormatElement(node)) {
11940
              remove$5(node);
11941
            }
11942
          });
11943
        } else {
11944
          empty(elm);
11945
        }
11946
        append$1(elm, br);
11947
        return Optional.some(CaretPosition.before(br.dom));
11948
      } else {
11949
        return Optional.none();
11950
      }
11951
    };
11952
    const deleteNormalized = (elm, afterDeletePosOpt, schema, normalizeWhitespace) => {
11953
      const prevTextOpt = prevSibling(elm).filter(isText$b);
11954
      const nextTextOpt = nextSibling(elm).filter(isText$b);
11955
      remove$5(elm);
11956
      return lift3(prevTextOpt, nextTextOpt, afterDeletePosOpt, (prev, next, pos) => {
11957
        const prevNode = prev.dom, nextNode = next.dom;
11958
        const offset = prevNode.data.length;
11959
        mergeTextNodes(prevNode, nextNode, schema, normalizeWhitespace);
11960
        return pos.container() === nextNode ? CaretPosition(prevNode, offset) : pos;
11961
      }).orThunk(() => {
11962
        if (normalizeWhitespace) {
11963
          prevTextOpt.each(elm => normalizeWhitespaceBefore(elm.dom, elm.dom.length, schema));
11964
          nextTextOpt.each(elm => normalizeWhitespaceAfter(elm.dom, 0, schema));
11965
        }
11966
        return afterDeletePosOpt;
11967
      });
11968
    };
11969
    const isInlineElement = (editor, element) => has$2(editor.schema.getTextInlineElements(), name(element));
11970
    const deleteElement$2 = (editor, forward, elm, moveCaret = true, preserveEmptyCaret = false) => {
11971
      const afterDeletePos = findCaretPosOutsideElmAfterDelete(forward, editor.getBody(), elm.dom);
11972
      const parentBlock = ancestor$4(elm, curry(isBlock, editor), eqRawNode(editor.getBody()));
11973
      const normalizedAfterDeletePos = deleteNormalized(elm, afterDeletePos, editor.schema, isInlineElement(editor, elm));
11974
      if (editor.dom.isEmpty(editor.getBody())) {
11975
        editor.setContent('');
11976
        editor.selection.setCursorLocation();
11977
      } else {
11978
        parentBlock.bind(elm => paddEmptyBlock(elm, preserveEmptyCaret)).fold(() => {
11979
          if (moveCaret) {
11980
            setSelection$1(editor, forward, normalizedAfterDeletePos);
11981
          }
11982
        }, paddPos => {
11983
          if (moveCaret) {
11984
            setSelection$1(editor, forward, Optional.some(paddPos));
11985
          }
11986
        });
11987
      }
11988
    };
11989
 
11990
    const strongRtl = /[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/;
11991
    const hasStrongRtl = text => strongRtl.test(text);
11992
 
11993
    const isInlineTarget = (editor, elm) => is$1(SugarElement.fromDom(elm), getInlineBoundarySelector(editor)) && !isTransparentBlock(editor.schema, elm) && editor.dom.isEditable(elm);
11994
    const isRtl = element => {
11995
      var _a;
11996
      return DOMUtils.DOM.getStyle(element, 'direction', true) === 'rtl' || hasStrongRtl((_a = element.textContent) !== null && _a !== void 0 ? _a : '');
11997
    };
11998
    const findInlineParents = (isInlineTarget, rootNode, pos) => filter$5(DOMUtils.DOM.getParents(pos.container(), '*', rootNode), isInlineTarget);
11999
    const findRootInline = (isInlineTarget, rootNode, pos) => {
12000
      const parents = findInlineParents(isInlineTarget, rootNode, pos);
12001
      return Optional.from(parents[parents.length - 1]);
12002
    };
12003
    const hasSameParentBlock = (rootNode, node1, node2) => {
12004
      const block1 = getParentBlock$3(node1, rootNode);
12005
      const block2 = getParentBlock$3(node2, rootNode);
12006
      return isNonNullable(block1) && block1 === block2;
12007
    };
12008
    const isAtZwsp = pos => isBeforeInline(pos) || isAfterInline(pos);
12009
    const normalizePosition = (forward, pos) => {
12010
      const container = pos.container(), offset = pos.offset();
12011
      if (forward) {
12012
        if (isCaretContainerInline(container)) {
12013
          if (isText$a(container.nextSibling)) {
12014
            return CaretPosition(container.nextSibling, 0);
12015
          } else {
12016
            return CaretPosition.after(container);
12017
          }
12018
        } else {
12019
          return isBeforeInline(pos) ? CaretPosition(container, offset + 1) : pos;
12020
        }
12021
      } else {
12022
        if (isCaretContainerInline(container)) {
12023
          if (isText$a(container.previousSibling)) {
12024
            return CaretPosition(container.previousSibling, container.previousSibling.data.length);
12025
          } else {
12026
            return CaretPosition.before(container);
12027
          }
12028
        } else {
12029
          return isAfterInline(pos) ? CaretPosition(container, offset - 1) : pos;
12030
        }
12031
      }
12032
    };
12033
    const normalizeForwards = curry(normalizePosition, true);
12034
    const normalizeBackwards = curry(normalizePosition, false);
12035
 
12036
    const execCommandIgnoreInputEvents = (editor, command) => {
12037
      const inputBlocker = e => e.stopImmediatePropagation();
12038
      editor.on('beforeinput input', inputBlocker, true);
12039
      editor.getDoc().execCommand(command);
12040
      editor.off('beforeinput input', inputBlocker);
12041
    };
12042
    const execEditorDeleteCommand = editor => {
12043
      editor.execCommand('delete');
12044
    };
12045
    const execNativeDeleteCommand = editor => execCommandIgnoreInputEvents(editor, 'Delete');
12046
    const execNativeForwardDeleteCommand = editor => execCommandIgnoreInputEvents(editor, 'ForwardDelete');
12047
    const isBeforeRoot = rootNode => elm => is$2(parent(elm), rootNode, eq);
12048
    const isTextBlockOrListItem = element => isTextBlock$2(element) || isListItem$1(element);
12049
    const getParentBlock$2 = (rootNode, elm) => {
12050
      if (contains(rootNode, elm)) {
12051
        return closest$4(elm, isTextBlockOrListItem, isBeforeRoot(rootNode));
12052
      } else {
12053
        return Optional.none();
12054
      }
12055
    };
12056
    const paddEmptyBody = (editor, moveSelection = true) => {
12057
      if (editor.dom.isEmpty(editor.getBody())) {
12058
        editor.setContent('', { no_selection: !moveSelection });
12059
      }
12060
    };
12061
    const willDeleteLastPositionInElement = (forward, fromPos, elm) => lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => {
12062
      const normalizedFirstPos = normalizePosition(true, firstPos);
12063
      const normalizedLastPos = normalizePosition(false, lastPos);
12064
      const normalizedFromPos = normalizePosition(false, fromPos);
12065
      if (forward) {
12066
        return nextPosition(elm, normalizedFromPos).exists(nextPos => nextPos.isEqual(normalizedLastPos) && fromPos.isEqual(normalizedFirstPos));
12067
      } else {
12068
        return prevPosition(elm, normalizedFromPos).exists(prevPos => prevPos.isEqual(normalizedFirstPos) && fromPos.isEqual(normalizedLastPos));
12069
      }
12070
    }).getOr(true);
12071
    const freefallRtl = root => {
12072
      const child = isComment$1(root) ? prevSibling(root) : lastChild(root);
12073
      return child.bind(freefallRtl).orThunk(() => Optional.some(root));
12074
    };
12075
    const deleteRangeContents = (editor, rng, root, moveSelection = true) => {
12076
      var _a;
12077
      rng.deleteContents();
12078
      const lastNode = freefallRtl(root).getOr(root);
12079
      const lastBlock = SugarElement.fromDom((_a = editor.dom.getParent(lastNode.dom, editor.dom.isBlock)) !== null && _a !== void 0 ? _a : root.dom);
12080
      if (lastBlock.dom === editor.getBody()) {
12081
        paddEmptyBody(editor, moveSelection);
12082
      } else if (isEmpty$2(lastBlock)) {
12083
        fillWithPaddingBr(lastBlock);
12084
        if (moveSelection) {
12085
          editor.selection.setCursorLocation(lastBlock.dom, 0);
12086
        }
12087
      }
12088
      if (!eq(root, lastBlock)) {
12089
        const additionalCleanupNodes = is$2(parent(lastBlock), root) ? [] : siblings(lastBlock);
12090
        each$e(additionalCleanupNodes.concat(children$1(root)), node => {
12091
          if (!eq(node, lastBlock) && !contains(node, lastBlock) && isEmpty$2(node)) {
12092
            remove$5(node);
12093
          }
12094
        });
12095
      }
12096
    };
12097
 
12098
    const ancestor$1 = (scope, predicate, isRoot) => ancestor$4(scope, predicate, isRoot).isSome();
12099
    const sibling = (scope, predicate) => sibling$1(scope, predicate).isSome();
12100
    const descendant = (scope, predicate) => descendant$2(scope, predicate).isSome();
12101
 
12102
    const isRootFromElement = root => cur => eq(root, cur);
12103
    const getTableCells = table => descendants(table, 'td,th');
12104
    const getTable$1 = (node, isRoot) => getClosestTable(SugarElement.fromDom(node), isRoot);
12105
    const selectionInTableWithNestedTable = details => {
12106
      return lift2(details.startTable, details.endTable, (startTable, endTable) => {
12107
        const isStartTableParentOfEndTable = descendant(startTable, t => eq(t, endTable));
12108
        const isEndTableParentOfStartTable = descendant(endTable, t => eq(t, startTable));
12109
        return !isStartTableParentOfEndTable && !isEndTableParentOfStartTable ? details : {
12110
          ...details,
12111
          startTable: isStartTableParentOfEndTable ? Optional.none() : details.startTable,
12112
          endTable: isEndTableParentOfStartTable ? Optional.none() : details.endTable,
12113
          isSameTable: false,
12114
          isMultiTable: false
12115
        };
12116
      }).getOr(details);
12117
    };
12118
    const adjustQuirksInDetails = details => {
12119
      return selectionInTableWithNestedTable(details);
12120
    };
12121
    const getTableDetailsFromRange = (rng, isRoot) => {
12122
      const startTable = getTable$1(rng.startContainer, isRoot);
12123
      const endTable = getTable$1(rng.endContainer, isRoot);
12124
      const isStartInTable = startTable.isSome();
12125
      const isEndInTable = endTable.isSome();
12126
      const isSameTable = lift2(startTable, endTable, eq).getOr(false);
12127
      const isMultiTable = !isSameTable && isStartInTable && isEndInTable;
12128
      return adjustQuirksInDetails({
12129
        startTable,
12130
        endTable,
12131
        isStartInTable,
12132
        isEndInTable,
12133
        isSameTable,
12134
        isMultiTable
12135
      });
12136
    };
12137
 
12138
    const tableCellRng = (start, end) => ({
12139
      start,
12140
      end
12141
    });
12142
    const tableSelection = (rng, table, cells) => ({
12143
      rng,
12144
      table,
12145
      cells
12146
    });
12147
    const deleteAction = Adt.generate([
12148
      {
12149
        singleCellTable: [
12150
          'rng',
12151
          'cell'
12152
        ]
12153
      },
12154
      { fullTable: ['table'] },
12155
      {
12156
        partialTable: [
12157
          'cells',
12158
          'outsideDetails'
12159
        ]
12160
      },
12161
      {
12162
        multiTable: [
12163
          'startTableCells',
12164
          'endTableCells',
12165
          'betweenRng'
12166
        ]
12167
      }
12168
    ]);
12169
    const getClosestCell$1 = (container, isRoot) => closest$3(SugarElement.fromDom(container), 'td,th', isRoot);
12170
    const isExpandedCellRng = cellRng => !eq(cellRng.start, cellRng.end);
12171
    const getTableFromCellRng = (cellRng, isRoot) => getClosestTable(cellRng.start, isRoot).bind(startParentTable => getClosestTable(cellRng.end, isRoot).bind(endParentTable => someIf(eq(startParentTable, endParentTable), startParentTable)));
12172
    const isSingleCellTable = (cellRng, isRoot) => !isExpandedCellRng(cellRng) && getTableFromCellRng(cellRng, isRoot).exists(table => {
12173
      const rows = table.dom.rows;
12174
      return rows.length === 1 && rows[0].cells.length === 1;
12175
    });
12176
    const getCellRng = (rng, isRoot) => {
12177
      const startCell = getClosestCell$1(rng.startContainer, isRoot);
12178
      const endCell = getClosestCell$1(rng.endContainer, isRoot);
12179
      return lift2(startCell, endCell, tableCellRng);
12180
    };
12181
    const getCellRangeFromStartTable = isRoot => startCell => getClosestTable(startCell, isRoot).bind(table => last$3(getTableCells(table)).map(endCell => tableCellRng(startCell, endCell)));
12182
    const getCellRangeFromEndTable = isRoot => endCell => getClosestTable(endCell, isRoot).bind(table => head(getTableCells(table)).map(startCell => tableCellRng(startCell, endCell)));
12183
    const getTableSelectionFromCellRng = isRoot => cellRng => getTableFromCellRng(cellRng, isRoot).map(table => tableSelection(cellRng, table, getTableCells(table)));
12184
    const getTableSelections = (cellRng, selectionDetails, rng, isRoot) => {
12185
      if (rng.collapsed || !cellRng.forall(isExpandedCellRng)) {
12186
        return Optional.none();
12187
      } else if (selectionDetails.isSameTable) {
12188
        const sameTableSelection = cellRng.bind(getTableSelectionFromCellRng(isRoot));
12189
        return Optional.some({
12190
          start: sameTableSelection,
12191
          end: sameTableSelection
12192
        });
12193
      } else {
12194
        const startCell = getClosestCell$1(rng.startContainer, isRoot);
12195
        const endCell = getClosestCell$1(rng.endContainer, isRoot);
12196
        const startTableSelection = startCell.bind(getCellRangeFromStartTable(isRoot)).bind(getTableSelectionFromCellRng(isRoot));
12197
        const endTableSelection = endCell.bind(getCellRangeFromEndTable(isRoot)).bind(getTableSelectionFromCellRng(isRoot));
12198
        return Optional.some({
12199
          start: startTableSelection,
12200
          end: endTableSelection
12201
        });
12202
      }
12203
    };
12204
    const getCellIndex = (cells, cell) => findIndex$2(cells, x => eq(x, cell));
12205
    const getSelectedCells = tableSelection => lift2(getCellIndex(tableSelection.cells, tableSelection.rng.start), getCellIndex(tableSelection.cells, tableSelection.rng.end), (startIndex, endIndex) => tableSelection.cells.slice(startIndex, endIndex + 1));
12206
    const isSingleCellTableContentSelected = (optCellRng, rng, isRoot) => optCellRng.exists(cellRng => isSingleCellTable(cellRng, isRoot) && hasAllContentsSelected(cellRng.start, rng));
12207
    const unselectCells = (rng, selectionDetails) => {
12208
      const {startTable, endTable} = selectionDetails;
12209
      const otherContentRng = rng.cloneRange();
12210
      startTable.each(table => otherContentRng.setStartAfter(table.dom));
12211
      endTable.each(table => otherContentRng.setEndBefore(table.dom));
12212
      return otherContentRng;
12213
    };
12214
    const handleSingleTable = (cellRng, selectionDetails, rng, isRoot) => getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(({start, end}) => start.or(end)).bind(tableSelection => {
12215
      const {isSameTable} = selectionDetails;
12216
      const selectedCells = getSelectedCells(tableSelection).getOr([]);
12217
      if (isSameTable && tableSelection.cells.length === selectedCells.length) {
12218
        return Optional.some(deleteAction.fullTable(tableSelection.table));
12219
      } else if (selectedCells.length > 0) {
12220
        if (isSameTable) {
12221
          return Optional.some(deleteAction.partialTable(selectedCells, Optional.none()));
12222
        } else {
12223
          const otherContentRng = unselectCells(rng, selectionDetails);
12224
          return Optional.some(deleteAction.partialTable(selectedCells, Optional.some({
12225
            ...selectionDetails,
12226
            rng: otherContentRng
12227
          })));
12228
        }
12229
      } else {
12230
        return Optional.none();
12231
      }
12232
    });
12233
    const handleMultiTable = (cellRng, selectionDetails, rng, isRoot) => getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(({start, end}) => {
12234
      const startTableSelectedCells = start.bind(getSelectedCells).getOr([]);
12235
      const endTableSelectedCells = end.bind(getSelectedCells).getOr([]);
12236
      if (startTableSelectedCells.length > 0 && endTableSelectedCells.length > 0) {
12237
        const otherContentRng = unselectCells(rng, selectionDetails);
12238
        return Optional.some(deleteAction.multiTable(startTableSelectedCells, endTableSelectedCells, otherContentRng));
12239
      } else {
12240
        return Optional.none();
12241
      }
12242
    });
12243
    const getActionFromRange = (root, rng) => {
12244
      const isRoot = isRootFromElement(root);
12245
      const optCellRng = getCellRng(rng, isRoot);
12246
      const selectionDetails = getTableDetailsFromRange(rng, isRoot);
12247
      if (isSingleCellTableContentSelected(optCellRng, rng, isRoot)) {
12248
        return optCellRng.map(cellRng => deleteAction.singleCellTable(rng, cellRng.start));
12249
      } else if (selectionDetails.isMultiTable) {
12250
        return handleMultiTable(optCellRng, selectionDetails, rng, isRoot);
12251
      } else {
12252
        return handleSingleTable(optCellRng, selectionDetails, rng, isRoot);
12253
      }
12254
    };
12255
 
12256
    const cleanCells = cells => each$e(cells, cell => {
12257
      remove$a(cell, 'contenteditable');
12258
      fillWithPaddingBr(cell);
12259
    });
12260
    const getOutsideBlock = (editor, container) => Optional.from(editor.dom.getParent(container, editor.dom.isBlock)).map(SugarElement.fromDom);
12261
    const handleEmptyBlock = (editor, startInTable, emptyBlock) => {
12262
      emptyBlock.each(block => {
12263
        if (startInTable) {
12264
          remove$5(block);
12265
        } else {
12266
          fillWithPaddingBr(block);
12267
          editor.selection.setCursorLocation(block.dom, 0);
12268
        }
12269
      });
12270
    };
12271
    const deleteContentInsideCell = (editor, cell, rng, isFirstCellInSelection) => {
12272
      const insideTableRng = rng.cloneRange();
12273
      if (isFirstCellInSelection) {
12274
        insideTableRng.setStart(rng.startContainer, rng.startOffset);
12275
        insideTableRng.setEndAfter(cell.dom.lastChild);
12276
      } else {
12277
        insideTableRng.setStartBefore(cell.dom.firstChild);
12278
        insideTableRng.setEnd(rng.endContainer, rng.endOffset);
12279
      }
12280
      deleteCellContents(editor, insideTableRng, cell, false).each(action => action());
12281
    };
12282
    const collapseAndRestoreCellSelection = editor => {
12283
      const selectedCells = getCellsFromEditor(editor);
12284
      const selectedNode = SugarElement.fromDom(editor.selection.getNode());
12285
      if (isTableCell$3(selectedNode.dom) && isEmpty$2(selectedNode)) {
12286
        editor.selection.setCursorLocation(selectedNode.dom, 0);
12287
      } else {
12288
        editor.selection.collapse(true);
12289
      }
12290
      if (selectedCells.length > 1 && exists(selectedCells, cell => eq(cell, selectedNode))) {
12291
        set$3(selectedNode, 'data-mce-selected', '1');
12292
      }
12293
    };
12294
    const emptySingleTableCells = (editor, cells, outsideDetails) => Optional.some(() => {
12295
      const editorRng = editor.selection.getRng();
12296
      const cellsToClean = outsideDetails.bind(({rng, isStartInTable}) => {
12297
        const outsideBlock = getOutsideBlock(editor, isStartInTable ? rng.endContainer : rng.startContainer);
12298
        rng.deleteContents();
12299
        handleEmptyBlock(editor, isStartInTable, outsideBlock.filter(isEmpty$2));
12300
        const endPointCell = isStartInTable ? cells[0] : cells[cells.length - 1];
12301
        deleteContentInsideCell(editor, endPointCell, editorRng, isStartInTable);
12302
        if (!isEmpty$2(endPointCell)) {
12303
          return Optional.some(isStartInTable ? cells.slice(1) : cells.slice(0, -1));
12304
        } else {
12305
          return Optional.none();
12306
        }
12307
      }).getOr(cells);
12308
      cleanCells(cellsToClean);
12309
      collapseAndRestoreCellSelection(editor);
12310
    });
12311
    const emptyMultiTableCells = (editor, startTableCells, endTableCells, betweenRng) => Optional.some(() => {
12312
      const rng = editor.selection.getRng();
12313
      const startCell = startTableCells[0];
12314
      const endCell = endTableCells[endTableCells.length - 1];
12315
      deleteContentInsideCell(editor, startCell, rng, true);
12316
      deleteContentInsideCell(editor, endCell, rng, false);
12317
      const startTableCellsToClean = isEmpty$2(startCell) ? startTableCells : startTableCells.slice(1);
12318
      const endTableCellsToClean = isEmpty$2(endCell) ? endTableCells : endTableCells.slice(0, -1);
12319
      cleanCells(startTableCellsToClean.concat(endTableCellsToClean));
12320
      betweenRng.deleteContents();
12321
      collapseAndRestoreCellSelection(editor);
12322
    });
12323
    const deleteCellContents = (editor, rng, cell, moveSelection = true) => Optional.some(() => {
12324
      deleteRangeContents(editor, rng, cell, moveSelection);
12325
    });
12326
    const deleteTableElement = (editor, table) => Optional.some(() => deleteElement$2(editor, false, table));
12327
    const deleteCellRange = (editor, rootElm, rng) => getActionFromRange(rootElm, rng).bind(action => action.fold(curry(deleteCellContents, editor), curry(deleteTableElement, editor), curry(emptySingleTableCells, editor), curry(emptyMultiTableCells, editor)));
12328
    const deleteCaptionRange = (editor, caption) => emptyElement(editor, caption);
12329
    const deleteTableRange = (editor, rootElm, rng, startElm) => getParentCaption(rootElm, startElm).fold(() => deleteCellRange(editor, rootElm, rng), caption => deleteCaptionRange(editor, caption));
12330
    const deleteRange$3 = (editor, startElm, selectedCells) => {
12331
      const rootNode = SugarElement.fromDom(editor.getBody());
12332
      const rng = editor.selection.getRng();
12333
      return selectedCells.length !== 0 ? emptySingleTableCells(editor, selectedCells, Optional.none()) : deleteTableRange(editor, rootNode, rng, startElm);
12334
    };
12335
    const getParentCell = (rootElm, elm) => find$2(parentsAndSelf(elm, rootElm), isTableCell$2);
12336
    const getParentCaption = (rootElm, elm) => find$2(parentsAndSelf(elm, rootElm), isTag('caption'));
12337
    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)));
12338
    const emptyElement = (editor, elm) => Optional.some(() => {
12339
      fillWithPaddingBr(elm);
12340
      editor.selection.setCursorLocation(elm.dom, 0);
12341
    });
12342
    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);
12343
    const emptyCaretCaption = (editor, elm) => emptyElement(editor, elm);
12344
    const validateCaretCaption = (rootElm, fromCaption, to) => getParentCaption(rootElm, SugarElement.fromDom(to.getNode())).fold(() => Optional.some(noop), toCaption => someIf(!eq(toCaption, fromCaption), noop));
12345
    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));
12346
    const deleteCaretCells = (editor, forward, rootElm, startElm) => {
12347
      const from = CaretPosition.fromRangeStart(editor.selection.getRng());
12348
      return getParentCell(rootElm, startElm).bind(fromCell => isEmpty$2(fromCell) ? emptyElement(editor, fromCell) : deleteBetweenCells(editor, rootElm, forward, fromCell, from));
12349
    };
12350
    const deleteCaretCaption = (editor, forward, rootElm, fromCaption) => {
12351
      const from = CaretPosition.fromRangeStart(editor.selection.getRng());
12352
      return isEmpty$2(fromCaption) ? emptyElement(editor, fromCaption) : deleteCaretInsideCaption(editor, rootElm, forward, fromCaption, from);
12353
    };
12354
    const isNearTable = (forward, pos) => forward ? isBeforeTable(pos) : isAfterTable(pos);
12355
    const isBeforeOrAfterTable = (editor, forward) => {
12356
      const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
12357
      return isNearTable(forward, fromPos) || fromPosition(forward, editor.getBody(), fromPos).exists(pos => isNearTable(forward, pos));
12358
    };
12359
    const deleteCaret$3 = (editor, forward, startElm) => {
12360
      const rootElm = SugarElement.fromDom(editor.getBody());
12361
      return getParentCaption(rootElm, startElm).fold(() => deleteCaretCells(editor, forward, rootElm, startElm).orThunk(() => someIf(isBeforeOrAfterTable(editor, forward), noop)), fromCaption => deleteCaretCaption(editor, forward, rootElm, fromCaption));
12362
    };
12363
    const backspaceDelete$a = (editor, forward) => {
12364
      const startElm = SugarElement.fromDom(editor.selection.getStart(true));
12365
      const cells = getCellsFromEditor(editor);
12366
      return editor.selection.isCollapsed() && cells.length === 0 ? deleteCaret$3(editor, forward, startElm) : deleteRange$3(editor, startElm, cells);
12367
    };
12368
 
12369
    const getContentEditableRoot$1 = (root, node) => {
12370
      let tempNode = node;
12371
      while (tempNode && tempNode !== root) {
12372
        if (isContentEditableTrue$3(tempNode) || isContentEditableFalse$b(tempNode)) {
12373
          return tempNode;
12374
        }
12375
        tempNode = tempNode.parentNode;
12376
      }
12377
      return null;
12378
    };
12379
 
12380
    const internalAttributesPrefixes = [
12381
      'data-ephox-',
12382
      'data-mce-',
12383
      'data-alloy-',
12384
      'data-snooker-',
12385
      '_'
12386
    ];
12387
    const each$9 = Tools.each;
12388
    const ElementUtils = editor => {
12389
      const dom = editor.dom;
12390
      const internalAttributes = new Set(editor.serializer.getTempAttrs());
12391
      const compare = (node1, node2) => {
12392
        if (node1.nodeName !== node2.nodeName || node1.nodeType !== node2.nodeType) {
12393
          return false;
12394
        }
12395
        const getAttribs = node => {
12396
          const attribs = {};
12397
          each$9(dom.getAttribs(node), attr => {
12398
            const name = attr.nodeName.toLowerCase();
12399
            if (name !== 'style' && !isAttributeInternal(name)) {
12400
              attribs[name] = dom.getAttrib(node, name);
12401
            }
12402
          });
12403
          return attribs;
12404
        };
12405
        const compareObjects = (obj1, obj2) => {
12406
          for (const name in obj1) {
12407
            if (has$2(obj1, name)) {
12408
              const value = obj2[name];
12409
              if (isUndefined(value)) {
12410
                return false;
12411
              }
12412
              if (obj1[name] !== value) {
12413
                return false;
12414
              }
12415
              delete obj2[name];
12416
            }
12417
          }
12418
          for (const name in obj2) {
12419
            if (has$2(obj2, name)) {
12420
              return false;
12421
            }
12422
          }
12423
          return true;
12424
        };
12425
        if (isElement$6(node1) && isElement$6(node2)) {
12426
          if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
12427
            return false;
12428
          }
12429
          if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) {
12430
            return false;
12431
          }
12432
        }
12433
        return !isBookmarkNode$1(node1) && !isBookmarkNode$1(node2);
12434
      };
12435
      const isAttributeInternal = attributeName => exists(internalAttributesPrefixes, value => startsWith(attributeName, value)) || internalAttributes.has(attributeName);
12436
      return {
12437
        compare,
12438
        isAttributeInternal
12439
      };
12440
    };
12441
 
12442
    const isHeading = node => [
12443
      'h1',
12444
      'h2',
12445
      'h3',
12446
      'h4',
12447
      'h5',
12448
      'h6'
12449
    ].includes(node.name);
12450
    const isSummary = node => node.name === 'summary';
12451
 
12452
    const traverse = (root, fn) => {
12453
      let node = root;
12454
      while (node = node.walk()) {
12455
        fn(node);
12456
      }
12457
    };
12458
    const matchNode$1 = (nodeFilters, attributeFilters, node, matches) => {
12459
      const name = node.name;
12460
      for (let ni = 0, nl = nodeFilters.length; ni < nl; ni++) {
12461
        const filter = nodeFilters[ni];
12462
        if (filter.name === name) {
12463
          const match = matches.nodes[name];
12464
          if (match) {
12465
            match.nodes.push(node);
12466
          } else {
12467
            matches.nodes[name] = {
12468
              filter,
12469
              nodes: [node]
12470
            };
12471
          }
12472
        }
12473
      }
12474
      if (node.attributes) {
12475
        for (let ai = 0, al = attributeFilters.length; ai < al; ai++) {
12476
          const filter = attributeFilters[ai];
12477
          const attrName = filter.name;
12478
          if (attrName in node.attributes.map) {
12479
            const match = matches.attributes[attrName];
12480
            if (match) {
12481
              match.nodes.push(node);
12482
            } else {
12483
              matches.attributes[attrName] = {
12484
                filter,
12485
                nodes: [node]
12486
              };
12487
            }
12488
          }
12489
        }
12490
      }
12491
    };
12492
    const findMatchingNodes = (nodeFilters, attributeFilters, node) => {
12493
      const matches = {
12494
        nodes: {},
12495
        attributes: {}
12496
      };
12497
      if (node.firstChild) {
12498
        traverse(node, childNode => {
12499
          matchNode$1(nodeFilters, attributeFilters, childNode, matches);
12500
        });
12501
      }
12502
      return matches;
12503
    };
12504
    const runFilters = (matches, args) => {
12505
      const run = (matchRecord, filteringAttributes) => {
12506
        each$d(matchRecord, match => {
12507
          const nodes = from(match.nodes);
12508
          each$e(match.filter.callbacks, callback => {
12509
            for (let i = nodes.length - 1; i >= 0; i--) {
12510
              const node = nodes[i];
12511
              const valueMatches = filteringAttributes ? node.attr(match.filter.name) !== undefined : node.name === match.filter.name;
12512
              if (!valueMatches || isNullable(node.parent)) {
12513
                nodes.splice(i, 1);
12514
              }
12515
            }
12516
            if (nodes.length > 0) {
12517
              callback(nodes, match.filter.name, args);
12518
            }
12519
          });
12520
        });
12521
      };
12522
      run(matches.nodes, false);
12523
      run(matches.attributes, true);
12524
    };
12525
    const filter$2 = (nodeFilters, attributeFilters, node, args = {}) => {
12526
      const matches = findMatchingNodes(nodeFilters, attributeFilters, node);
12527
      runFilters(matches, args);
12528
    };
12529
 
12530
    const paddEmptyNode = (settings, args, isBlock, node) => {
12531
      const brPreferred = settings.pad_empty_with_br || args.insert;
12532
      if (brPreferred && isBlock(node)) {
12533
        const astNode = new AstNode('br', 1);
12534
        if (args.insert) {
12535
          astNode.attr('data-mce-bogus', '1');
12536
        }
12537
        node.empty().append(astNode);
12538
      } else {
12539
        node.empty().append(new AstNode('#text', 3)).value = nbsp;
12540
      }
12541
    };
12542
    const isPaddedWithNbsp = node => {
12543
      var _a;
12544
      return hasOnlyChild(node, '#text') && ((_a = node === null || node === void 0 ? void 0 : node.firstChild) === null || _a === void 0 ? void 0 : _a.value) === nbsp;
12545
    };
12546
    const hasOnlyChild = (node, name) => {
12547
      const firstChild = node === null || node === void 0 ? void 0 : node.firstChild;
12548
      return isNonNullable(firstChild) && firstChild === node.lastChild && firstChild.name === name;
12549
    };
12550
    const isPadded = (schema, node) => {
12551
      const rule = schema.getElementRule(node.name);
12552
      return (rule === null || rule === void 0 ? void 0 : rule.paddEmpty) === true;
12553
    };
12554
    const isEmpty = (schema, nonEmptyElements, whitespaceElements, node) => node.isEmpty(nonEmptyElements, whitespaceElements, node => isPadded(schema, node));
12555
    const isLineBreakNode = (node, isBlock) => isNonNullable(node) && (isBlock(node) || node.name === 'br');
12556
    const findClosestEditingHost = scope => {
12557
      let editableNode;
12558
      for (let node = scope; node; node = node.parent) {
12559
        const contentEditable = node.attr('contenteditable');
12560
        if (contentEditable === 'false') {
12561
          break;
12562
        } else if (contentEditable === 'true') {
12563
          editableNode = node;
12564
        }
12565
      }
12566
      return Optional.from(editableNode);
12567
    };
12568
 
12569
    const removeOrUnwrapInvalidNode = (node, schema, originalNodeParent = node.parent) => {
12570
      if (schema.getSpecialElements()[node.name]) {
12571
        node.empty().remove();
12572
      } else {
12573
        const children = node.children();
12574
        for (const childNode of children) {
12575
          if (originalNodeParent && !schema.isValidChild(originalNodeParent.name, childNode.name)) {
12576
            removeOrUnwrapInvalidNode(childNode, schema, originalNodeParent);
12577
          }
12578
        }
12579
        node.unwrap();
12580
      }
12581
    };
12582
    const cleanInvalidNodes = (nodes, schema, rootNode, onCreate = noop) => {
12583
      const textBlockElements = schema.getTextBlockElements();
12584
      const nonEmptyElements = schema.getNonEmptyElements();
12585
      const whitespaceElements = schema.getWhitespaceElements();
12586
      const nonSplittableElements = Tools.makeMap('tr,td,th,tbody,thead,tfoot,table,summary');
12587
      const fixed = new Set();
12588
      const isSplittableElement = node => node !== rootNode && !nonSplittableElements[node.name];
12589
      for (let ni = 0; ni < nodes.length; ni++) {
12590
        const node = nodes[ni];
12591
        let parent;
12592
        let newParent;
12593
        let tempNode;
12594
        if (!node.parent || fixed.has(node)) {
12595
          continue;
12596
        }
12597
        if (textBlockElements[node.name] && node.parent.name === 'li') {
12598
          let sibling = node.next;
12599
          while (sibling) {
12600
            if (textBlockElements[sibling.name]) {
12601
              sibling.name = 'li';
12602
              fixed.add(sibling);
12603
              node.parent.insert(sibling, node.parent);
12604
            } else {
12605
              break;
12606
            }
12607
            sibling = sibling.next;
12608
          }
12609
          node.unwrap();
12610
          continue;
12611
        }
12612
        const parents = [node];
12613
        for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && isSplittableElement(parent); parent = parent.parent) {
12614
          parents.push(parent);
12615
        }
12616
        if (parent && parents.length > 1) {
12617
          if (!isInvalid(schema, node, parent)) {
12618
            parents.reverse();
12619
            newParent = parents[0].clone();
12620
            onCreate(newParent);
12621
            let currentNode = newParent;
12622
            for (let i = 0; i < parents.length - 1; i++) {
12623
              if (schema.isValidChild(currentNode.name, parents[i].name) && i > 0) {
12624
                tempNode = parents[i].clone();
12625
                onCreate(tempNode);
12626
                currentNode.append(tempNode);
12627
              } else {
12628
                tempNode = currentNode;
12629
              }
12630
              for (let childNode = parents[i].firstChild; childNode && childNode !== parents[i + 1];) {
12631
                const nextNode = childNode.next;
12632
                tempNode.append(childNode);
12633
                childNode = nextNode;
12634
              }
12635
              currentNode = tempNode;
12636
            }
12637
            if (!isEmpty(schema, nonEmptyElements, whitespaceElements, newParent)) {
12638
              parent.insert(newParent, parents[0], true);
12639
              parent.insert(node, newParent);
12640
            } else {
12641
              parent.insert(node, parents[0], true);
12642
            }
12643
            parent = parents[0];
12644
            if (isEmpty(schema, nonEmptyElements, whitespaceElements, parent) || hasOnlyChild(parent, 'br')) {
12645
              parent.empty().remove();
12646
            }
12647
          } else {
12648
            removeOrUnwrapInvalidNode(node, schema);
12649
          }
12650
        } else if (node.parent) {
12651
          if (node.name === 'li') {
12652
            let sibling = node.prev;
12653
            if (sibling && (sibling.name === 'ul' || sibling.name === 'ol')) {
12654
              sibling.append(node);
12655
              continue;
12656
            }
12657
            sibling = node.next;
12658
            if (sibling && (sibling.name === 'ul' || sibling.name === 'ol') && sibling.firstChild) {
12659
              sibling.insert(node, sibling.firstChild, true);
12660
              continue;
12661
            }
12662
            const wrapper = new AstNode('ul', 1);
12663
            onCreate(wrapper);
12664
            node.wrap(wrapper);
12665
            continue;
12666
          }
12667
          if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) {
12668
            const wrapper = new AstNode('div', 1);
12669
            onCreate(wrapper);
12670
            node.wrap(wrapper);
12671
          } else {
12672
            removeOrUnwrapInvalidNode(node, schema);
12673
          }
12674
        }
12675
      }
12676
    };
12677
    const hasClosest = (node, parentName) => {
12678
      let tempNode = node;
12679
      while (tempNode) {
12680
        if (tempNode.name === parentName) {
12681
          return true;
12682
        }
12683
        tempNode = tempNode.parent;
12684
      }
12685
      return false;
12686
    };
12687
    const isInvalid = (schema, node, parent = node.parent) => {
12688
      if (!parent) {
12689
        return false;
12690
      }
12691
      if (schema.children[node.name] && !schema.isValidChild(parent.name, node.name)) {
12692
        return true;
12693
      }
12694
      if (node.name === 'a' && hasClosest(parent, 'a')) {
12695
        return true;
12696
      }
12697
      if (isSummary(parent) && isHeading(node)) {
12698
        return !((parent === null || parent === void 0 ? void 0 : parent.firstChild) === node && (parent === null || parent === void 0 ? void 0 : parent.lastChild) === node);
12699
      }
12700
      return false;
12701
    };
12702
 
12703
    const createRange = (sc, so, ec, eo) => {
12704
      const rng = document.createRange();
12705
      rng.setStart(sc, so);
12706
      rng.setEnd(ec, eo);
12707
      return rng;
12708
    };
12709
    const normalizeBlockSelectionRange = rng => {
12710
      const startPos = CaretPosition.fromRangeStart(rng);
12711
      const endPos = CaretPosition.fromRangeEnd(rng);
12712
      const rootNode = rng.commonAncestorContainer;
12713
      return fromPosition(false, rootNode, endPos).map(newEndPos => {
12714
        if (!isInSameBlock(startPos, endPos, rootNode) && isInSameBlock(startPos, newEndPos, rootNode)) {
12715
          return createRange(startPos.container(), startPos.offset(), newEndPos.container(), newEndPos.offset());
12716
        } else {
12717
          return rng;
12718
        }
12719
      }).getOr(rng);
12720
    };
12721
    const normalize = rng => rng.collapsed ? rng : normalizeBlockSelectionRange(rng);
12722
 
12723
    const hasOnlyOneChild$1 = node => {
12724
      return isNonNullable(node.firstChild) && node.firstChild === node.lastChild;
12725
    };
12726
    const isPaddingNode = node => {
12727
      return node.name === 'br' || node.value === nbsp;
12728
    };
12729
    const isPaddedEmptyBlock = (schema, node) => {
12730
      const blockElements = schema.getBlockElements();
12731
      return blockElements[node.name] && hasOnlyOneChild$1(node) && isPaddingNode(node.firstChild);
12732
    };
12733
    const isEmptyFragmentElement = (schema, node) => {
12734
      const nonEmptyElements = schema.getNonEmptyElements();
12735
      return isNonNullable(node) && (node.isEmpty(nonEmptyElements) || isPaddedEmptyBlock(schema, node));
12736
    };
12737
    const isListFragment = (schema, fragment) => {
12738
      let firstChild = fragment.firstChild;
12739
      let lastChild = fragment.lastChild;
12740
      if (firstChild && firstChild.name === 'meta') {
12741
        firstChild = firstChild.next;
12742
      }
12743
      if (lastChild && lastChild.attr('id') === 'mce_marker') {
12744
        lastChild = lastChild.prev;
12745
      }
12746
      if (isEmptyFragmentElement(schema, lastChild)) {
12747
        lastChild = lastChild === null || lastChild === void 0 ? void 0 : lastChild.prev;
12748
      }
12749
      if (!firstChild || firstChild !== lastChild) {
12750
        return false;
12751
      }
12752
      return firstChild.name === 'ul' || firstChild.name === 'ol';
12753
    };
12754
    const cleanupDomFragment = domFragment => {
12755
      var _a, _b;
12756
      const firstChild = domFragment.firstChild;
12757
      const lastChild = domFragment.lastChild;
12758
      if (firstChild && firstChild.nodeName === 'META') {
12759
        (_a = firstChild.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(firstChild);
12760
      }
12761
      if (lastChild && lastChild.id === 'mce_marker') {
12762
        (_b = lastChild.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(lastChild);
12763
      }
12764
      return domFragment;
12765
    };
12766
    const toDomFragment = (dom, serializer, fragment) => {
12767
      const html = serializer.serialize(fragment);
12768
      const domFragment = dom.createFragment(html);
12769
      return cleanupDomFragment(domFragment);
12770
    };
12771
    const listItems = elm => {
12772
      var _a;
12773
      return filter$5((_a = elm === null || elm === void 0 ? void 0 : elm.childNodes) !== null && _a !== void 0 ? _a : [], child => {
12774
        return child.nodeName === 'LI';
12775
      });
12776
    };
12777
    const isPadding = node => {
12778
      return node.data === nbsp || isBr$6(node);
12779
    };
12780
    const isListItemPadded = node => {
12781
      return isNonNullable(node === null || node === void 0 ? void 0 : node.firstChild) && node.firstChild === node.lastChild && isPadding(node.firstChild);
12782
    };
12783
    const isEmptyOrPadded = elm => {
12784
      return !elm.firstChild || isListItemPadded(elm);
12785
    };
12786
    const trimListItems = elms => {
12787
      return elms.length > 0 && isEmptyOrPadded(elms[elms.length - 1]) ? elms.slice(0, -1) : elms;
12788
    };
12789
    const getParentLi = (dom, node) => {
12790
      const parentBlock = dom.getParent(node, dom.isBlock);
12791
      return parentBlock && parentBlock.nodeName === 'LI' ? parentBlock : null;
12792
    };
12793
    const isParentBlockLi = (dom, node) => {
12794
      return !!getParentLi(dom, node);
12795
    };
12796
    const getSplit = (parentNode, rng) => {
12797
      const beforeRng = rng.cloneRange();
12798
      const afterRng = rng.cloneRange();
12799
      beforeRng.setStartBefore(parentNode);
12800
      afterRng.setEndAfter(parentNode);
12801
      return [
12802
        beforeRng.cloneContents(),
12803
        afterRng.cloneContents()
12804
      ];
12805
    };
12806
    const findFirstIn = (node, rootNode) => {
12807
      const caretPos = CaretPosition.before(node);
12808
      const caretWalker = CaretWalker(rootNode);
12809
      const newCaretPos = caretWalker.next(caretPos);
12810
      return newCaretPos ? newCaretPos.toRange() : null;
12811
    };
12812
    const findLastOf = (node, rootNode) => {
12813
      const caretPos = CaretPosition.after(node);
12814
      const caretWalker = CaretWalker(rootNode);
12815
      const newCaretPos = caretWalker.prev(caretPos);
12816
      return newCaretPos ? newCaretPos.toRange() : null;
12817
    };
12818
    const insertMiddle = (target, elms, rootNode, rng) => {
12819
      const parts = getSplit(target, rng);
12820
      const parentElm = target.parentNode;
12821
      if (parentElm) {
12822
        parentElm.insertBefore(parts[0], target);
12823
        Tools.each(elms, li => {
12824
          parentElm.insertBefore(li, target);
12825
        });
12826
        parentElm.insertBefore(parts[1], target);
12827
        parentElm.removeChild(target);
12828
      }
12829
      return findLastOf(elms[elms.length - 1], rootNode);
12830
    };
12831
    const insertBefore$2 = (target, elms, rootNode) => {
12832
      const parentElm = target.parentNode;
12833
      if (parentElm) {
12834
        Tools.each(elms, elm => {
12835
          parentElm.insertBefore(elm, target);
12836
        });
12837
      }
12838
      return findFirstIn(target, rootNode);
12839
    };
12840
    const insertAfter$2 = (target, elms, rootNode, dom) => {
12841
      dom.insertAfter(elms.reverse(), target);
12842
      return findLastOf(elms[0], rootNode);
12843
    };
12844
    const insertAtCaret$1 = (serializer, dom, rng, fragment) => {
12845
      const domFragment = toDomFragment(dom, serializer, fragment);
12846
      const liTarget = getParentLi(dom, rng.startContainer);
12847
      const liElms = trimListItems(listItems(domFragment.firstChild));
12848
      const BEGINNING = 1, END = 2;
12849
      const rootNode = dom.getRoot();
12850
      const isAt = location => {
12851
        const caretPos = CaretPosition.fromRangeStart(rng);
12852
        const caretWalker = CaretWalker(dom.getRoot());
12853
        const newPos = location === BEGINNING ? caretWalker.prev(caretPos) : caretWalker.next(caretPos);
12854
        const newPosNode = newPos === null || newPos === void 0 ? void 0 : newPos.getNode();
12855
        return newPosNode ? getParentLi(dom, newPosNode) !== liTarget : true;
12856
      };
12857
      if (!liTarget) {
12858
        return null;
12859
      } else if (isAt(BEGINNING)) {
12860
        return insertBefore$2(liTarget, liElms, rootNode);
12861
      } else if (isAt(END)) {
12862
        return insertAfter$2(liTarget, liElms, rootNode, dom);
12863
      } else {
12864
        return insertMiddle(liTarget, liElms, rootNode, rng);
12865
      }
12866
    };
12867
 
12868
    const mergeableWrappedElements = ['pre'];
12869
    const shouldPasteContentOnly = (dom, fragment, parentNode, root) => {
12870
      var _a;
12871
      const firstNode = fragment.firstChild;
12872
      const lastNode = fragment.lastChild;
12873
      const last = lastNode.attr('data-mce-type') === 'bookmark' ? lastNode.prev : lastNode;
12874
      const isPastingSingleElement = firstNode === last;
12875
      const isWrappedElement = contains$2(mergeableWrappedElements, firstNode.name);
12876
      if (isPastingSingleElement && isWrappedElement) {
12877
        const isContentEditable = firstNode.attr('contenteditable') !== 'false';
12878
        const isPastingInTheSameBlockTag = ((_a = dom.getParent(parentNode, dom.isBlock)) === null || _a === void 0 ? void 0 : _a.nodeName.toLowerCase()) === firstNode.name;
12879
        const isPastingInContentEditable = Optional.from(getContentEditableRoot$1(root, parentNode)).forall(isContentEditableTrue$3);
12880
        return isContentEditable && isPastingInTheSameBlockTag && isPastingInContentEditable;
12881
      } else {
12882
        return false;
12883
      }
12884
    };
12885
    const isTableCell = isTableCell$3;
12886
    const isTableCellContentSelected = (dom, rng, cell) => {
12887
      if (isNonNullable(cell)) {
12888
        const endCell = dom.getParent(rng.endContainer, isTableCell);
12889
        return cell === endCell && hasAllContentsSelected(SugarElement.fromDom(cell), rng);
12890
      } else {
12891
        return false;
12892
      }
12893
    };
12894
    const validInsertion = (editor, value, parentNode) => {
12895
      var _a;
12896
      if (parentNode.getAttribute('data-mce-bogus') === 'all') {
12897
        (_a = parentNode.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(editor.dom.createFragment(value), parentNode);
12898
      } else {
12899
        const node = parentNode.firstChild;
12900
        const node2 = parentNode.lastChild;
12901
        if (!node || node === node2 && node.nodeName === 'BR') {
12902
          editor.dom.setHTML(parentNode, value);
12903
        } else {
12904
          editor.selection.setContent(value, { no_events: true });
12905
        }
12906
      }
12907
    };
12908
    const trimBrsFromTableCell = (dom, elm, schema) => {
12909
      Optional.from(dom.getParent(elm, 'td,th')).map(SugarElement.fromDom).each(el => trimBlockTrailingBr(el, schema));
12910
    };
12911
    const reduceInlineTextElements = (editor, merge) => {
12912
      const textInlineElements = editor.schema.getTextInlineElements();
12913
      const dom = editor.dom;
12914
      if (merge) {
12915
        const root = editor.getBody();
12916
        const elementUtils = ElementUtils(editor);
12917
        Tools.each(dom.select('*[data-mce-fragment]'), node => {
12918
          const isInline = isNonNullable(textInlineElements[node.nodeName.toLowerCase()]);
12919
          if (isInline && hasInheritableStyles(dom, node)) {
12920
            for (let parentNode = node.parentElement; isNonNullable(parentNode) && parentNode !== root; parentNode = parentNode.parentElement) {
12921
              const styleConflict = hasStyleConflict(dom, node, parentNode);
12922
              if (styleConflict) {
12923
                break;
12924
              }
12925
              if (elementUtils.compare(parentNode, node)) {
12926
                dom.remove(node, true);
12927
                break;
12928
              }
12929
            }
12930
          }
12931
        });
12932
      }
12933
    };
12934
    const markFragmentElements = fragment => {
12935
      let node = fragment;
12936
      while (node = node.walk()) {
12937
        if (node.type === 1) {
12938
          node.attr('data-mce-fragment', '1');
12939
        }
12940
      }
12941
    };
12942
    const unmarkFragmentElements = elm => {
12943
      Tools.each(elm.getElementsByTagName('*'), elm => {
12944
        elm.removeAttribute('data-mce-fragment');
12945
      });
12946
    };
12947
    const isPartOfFragment = node => {
12948
      return !!node.getAttribute('data-mce-fragment');
12949
    };
12950
    const canHaveChildren = (editor, node) => {
12951
      return isNonNullable(node) && !editor.schema.getVoidElements()[node.nodeName];
12952
    };
12953
    const moveSelectionToMarker = (editor, marker) => {
12954
      var _a, _b, _c;
12955
      let nextRng;
12956
      const dom = editor.dom;
12957
      const selection = editor.selection;
12958
      if (!marker) {
12959
        return;
12960
      }
12961
      selection.scrollIntoView(marker);
12962
      const parentEditableElm = getContentEditableRoot$1(editor.getBody(), marker);
12963
      if (parentEditableElm && dom.getContentEditable(parentEditableElm) === 'false') {
12964
        dom.remove(marker);
12965
        selection.select(parentEditableElm);
12966
        return;
12967
      }
12968
      let rng = dom.createRng();
12969
      const node = marker.previousSibling;
12970
      if (isText$a(node)) {
12971
        rng.setStart(node, (_b = (_a = node.nodeValue) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0);
12972
        const node2 = marker.nextSibling;
12973
        if (isText$a(node2)) {
12974
          node.appendData(node2.data);
12975
          (_c = node2.parentNode) === null || _c === void 0 ? void 0 : _c.removeChild(node2);
12976
        }
12977
      } else {
12978
        rng.setStartBefore(marker);
12979
        rng.setEndBefore(marker);
12980
      }
12981
      const findNextCaretRng = rng => {
12982
        let caretPos = CaretPosition.fromRangeStart(rng);
12983
        const caretWalker = CaretWalker(editor.getBody());
12984
        caretPos = caretWalker.next(caretPos);
12985
        return caretPos === null || caretPos === void 0 ? void 0 : caretPos.toRange();
12986
      };
12987
      const parentBlock = dom.getParent(marker, dom.isBlock);
12988
      dom.remove(marker);
12989
      if (parentBlock && dom.isEmpty(parentBlock)) {
12990
        const isCell = isTableCell(parentBlock);
12991
        empty(SugarElement.fromDom(parentBlock));
12992
        rng.setStart(parentBlock, 0);
12993
        rng.setEnd(parentBlock, 0);
12994
        if (!isCell && !isPartOfFragment(parentBlock) && (nextRng = findNextCaretRng(rng))) {
12995
          rng = nextRng;
12996
          dom.remove(parentBlock);
12997
        } else {
12998
          dom.add(parentBlock, dom.create('br', isCell ? {} : { 'data-mce-bogus': '1' }));
12999
        }
13000
      }
13001
      selection.setRng(rng);
13002
    };
13003
    const deleteSelectedContent = editor => {
13004
      const dom = editor.dom;
13005
      const rng = normalize(editor.selection.getRng());
13006
      editor.selection.setRng(rng);
13007
      const startCell = dom.getParent(rng.startContainer, isTableCell);
13008
      if (isTableCellContentSelected(dom, rng, startCell)) {
13009
        deleteCellContents(editor, rng, SugarElement.fromDom(startCell));
13010
      } else if (rng.startContainer === rng.endContainer && rng.endOffset - rng.startOffset === 1 && isText$a(rng.startContainer.childNodes[rng.startOffset])) {
13011
        rng.deleteContents();
13012
      } else {
13013
        editor.getDoc().execCommand('Delete', false);
13014
      }
13015
    };
13016
    const findMarkerNode = scope => {
13017
      for (let markerNode = scope; markerNode; markerNode = markerNode.walk()) {
13018
        if (markerNode.attr('id') === 'mce_marker') {
13019
          return Optional.some(markerNode);
13020
        }
13021
      }
13022
      return Optional.none();
13023
    };
13024
    const notHeadingsInSummary = (dom, node, fragment) => {
13025
      var _a;
13026
      return exists(fragment.children(), isHeading) && ((_a = dom.getParent(node, dom.isBlock)) === null || _a === void 0 ? void 0 : _a.nodeName) === 'SUMMARY';
13027
    };
13028
    const insertHtmlAtCaret = (editor, value, details) => {
13029
      var _a, _b;
13030
      const selection = editor.selection;
13031
      const dom = editor.dom;
13032
      const parser = editor.parser;
13033
      const merge = details.merge;
13034
      const serializer = HtmlSerializer({ validate: true }, editor.schema);
13035
      const bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;</span>';
13036
      if (!details.preserve_zwsp) {
13037
        value = trim$2(value);
13038
      }
13039
      if (value.indexOf('{$caret}') === -1) {
13040
        value += '{$caret}';
13041
      }
13042
      value = value.replace(/\{\$caret\}/, bookmarkHtml);
13043
      let rng = selection.getRng();
13044
      const caretElement = rng.startContainer;
13045
      const body = editor.getBody();
13046
      if (caretElement === body && selection.isCollapsed()) {
13047
        if (dom.isBlock(body.firstChild) && canHaveChildren(editor, body.firstChild) && dom.isEmpty(body.firstChild)) {
13048
          rng = dom.createRng();
13049
          rng.setStart(body.firstChild, 0);
13050
          rng.setEnd(body.firstChild, 0);
13051
          selection.setRng(rng);
13052
        }
13053
      }
13054
      if (!selection.isCollapsed()) {
13055
        deleteSelectedContent(editor);
13056
      }
13057
      const parentNode = selection.getNode();
13058
      const parserArgs = {
13059
        context: parentNode.nodeName.toLowerCase(),
13060
        data: details.data,
13061
        insert: true
13062
      };
13063
      const fragment = parser.parse(value, parserArgs);
13064
      if (details.paste === true && isListFragment(editor.schema, fragment) && isParentBlockLi(dom, parentNode)) {
13065
        rng = insertAtCaret$1(serializer, dom, selection.getRng(), fragment);
13066
        if (rng) {
13067
          selection.setRng(rng);
13068
        }
13069
        return value;
13070
      }
13071
      if (details.paste === true && shouldPasteContentOnly(dom, fragment, parentNode, editor.getBody())) {
13072
        (_a = fragment.firstChild) === null || _a === void 0 ? void 0 : _a.unwrap();
13073
      }
13074
      markFragmentElements(fragment);
13075
      let node = fragment.lastChild;
13076
      if (node && node.attr('id') === 'mce_marker') {
13077
        const marker = node;
13078
        for (node = node.prev; node; node = node.walk(true)) {
13079
          if (node.type === 3 || !dom.isBlock(node.name)) {
13080
            if (node.parent && editor.schema.isValidChild(node.parent.name, 'span')) {
13081
              node.parent.insert(marker, node, node.name === 'br');
13082
            }
13083
            break;
13084
          }
13085
        }
13086
      }
13087
      editor._selectionOverrides.showBlockCaretContainer(parentNode);
13088
      if (!parserArgs.invalid && !notHeadingsInSummary(dom, parentNode, fragment)) {
13089
        value = serializer.serialize(fragment);
13090
        validInsertion(editor, value, parentNode);
13091
      } else {
13092
        editor.selection.setContent(bookmarkHtml);
13093
        let parentNode = selection.getNode();
13094
        let tempNode;
13095
        const rootNode = editor.getBody();
13096
        if (isDocument$1(parentNode)) {
13097
          parentNode = tempNode = rootNode;
13098
        } else {
13099
          tempNode = parentNode;
13100
        }
13101
        while (tempNode && tempNode !== rootNode) {
13102
          parentNode = tempNode;
13103
          tempNode = tempNode.parentNode;
13104
        }
13105
        value = parentNode === rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode);
13106
        const root = parser.parse(value);
13107
        const markerNode = findMarkerNode(root);
13108
        const editingHost = markerNode.bind(findClosestEditingHost).getOr(root);
13109
        markerNode.each(marker => marker.replace(fragment));
13110
        const toExtract = fragment.children();
13111
        const parent = (_b = fragment.parent) !== null && _b !== void 0 ? _b : root;
13112
        fragment.unwrap();
13113
        const invalidChildren = filter$5(toExtract, node => isInvalid(editor.schema, node, parent));
13114
        cleanInvalidNodes(invalidChildren, editor.schema, editingHost);
13115
        filter$2(parser.getNodeFilters(), parser.getAttributeFilters(), root);
13116
        value = serializer.serialize(root);
13117
        if (parentNode === rootNode) {
13118
          dom.setHTML(rootNode, value);
13119
        } else {
13120
          dom.setOuterHTML(parentNode, value);
13121
        }
13122
      }
13123
      reduceInlineTextElements(editor, merge);
13124
      moveSelectionToMarker(editor, dom.get('mce_marker'));
13125
      unmarkFragmentElements(editor.getBody());
13126
      trimBrsFromTableCell(dom, selection.getStart(), editor.schema);
13127
      updateCaret(editor.schema, editor.getBody(), selection.getStart());
13128
      return value;
13129
    };
13130
 
13131
    const isTreeNode = content => content instanceof AstNode;
13132
 
13133
    const moveSelection = editor => {
13134
      if (hasFocus(editor)) {
13135
        firstPositionIn(editor.getBody()).each(pos => {
13136
          const node = pos.getNode();
13137
          const caretPos = isTable$2(node) ? firstPositionIn(node).getOr(pos) : pos;
13138
          editor.selection.setRng(caretPos.toRange());
13139
        });
13140
      }
13141
    };
13142
    const setEditorHtml = (editor, html, noSelection) => {
13143
      editor.dom.setHTML(editor.getBody(), html);
13144
      if (noSelection !== true) {
13145
        moveSelection(editor);
13146
      }
13147
    };
13148
    const setContentString = (editor, body, content, args) => {
13149
      content = trim$2(content);
13150
      if (content.length === 0 || /^\s+$/.test(content)) {
13151
        const padd = '<br data-mce-bogus="1">';
13152
        if (body.nodeName === 'TABLE') {
13153
          content = '<tr><td>' + padd + '</td></tr>';
13154
        } else if (/^(UL|OL)$/.test(body.nodeName)) {
13155
          content = '<li>' + padd + '</li>';
13156
        }
13157
        const forcedRootBlockName = getForcedRootBlock(editor);
13158
        if (editor.schema.isValidChild(body.nodeName.toLowerCase(), forcedRootBlockName.toLowerCase())) {
13159
          content = padd;
13160
          content = editor.dom.createHTML(forcedRootBlockName, getForcedRootBlockAttrs(editor), content);
13161
        } else if (!content) {
13162
          content = padd;
13163
        }
13164
        setEditorHtml(editor, content, args.no_selection);
13165
        return {
13166
          content,
13167
          html: content
13168
        };
13169
      } else {
13170
        if (args.format !== 'raw') {
13171
          content = HtmlSerializer({ validate: false }, editor.schema).serialize(editor.parser.parse(content, {
13172
            isRootContent: true,
13173
            insert: true
13174
          }));
13175
        }
13176
        const trimmedHtml = isWsPreserveElement(SugarElement.fromDom(body)) ? content : Tools.trim(content);
13177
        setEditorHtml(editor, trimmedHtml, args.no_selection);
13178
        return {
13179
          content: trimmedHtml,
13180
          html: trimmedHtml
13181
        };
13182
      }
13183
    };
13184
    const setContentTree = (editor, body, content, args) => {
13185
      filter$2(editor.parser.getNodeFilters(), editor.parser.getAttributeFilters(), content);
13186
      const html = HtmlSerializer({ validate: false }, editor.schema).serialize(content);
13187
      const trimmedHtml = trim$2(isWsPreserveElement(SugarElement.fromDom(body)) ? html : Tools.trim(html));
13188
      setEditorHtml(editor, trimmedHtml, args.no_selection);
13189
      return {
13190
        content,
13191
        html: trimmedHtml
13192
      };
13193
    };
13194
    const setContentInternal = (editor, content, args) => {
13195
      return Optional.from(editor.getBody()).map(body => {
13196
        if (isTreeNode(content)) {
13197
          return setContentTree(editor, body, content, args);
13198
        } else {
13199
          return setContentString(editor, body, content, args);
13200
        }
13201
      }).getOr({
13202
        content,
13203
        html: isTreeNode(args.content) ? '' : args.content
13204
      });
13205
    };
13206
 
13207
    const ensureIsRoot = isRoot => isFunction(isRoot) ? isRoot : never;
13208
    const ancestor = (scope, transform, isRoot) => {
13209
      let element = scope.dom;
13210
      const stop = ensureIsRoot(isRoot);
13211
      while (element.parentNode) {
13212
        element = element.parentNode;
13213
        const el = SugarElement.fromDom(element);
13214
        const transformed = transform(el);
13215
        if (transformed.isSome()) {
13216
          return transformed;
13217
        } else if (stop(el)) {
13218
          break;
13219
        }
13220
      }
13221
      return Optional.none();
13222
    };
13223
    const closest$1 = (scope, transform, isRoot) => {
13224
      const current = transform(scope);
13225
      const stop = ensureIsRoot(isRoot);
13226
      return current.orThunk(() => stop(scope) ? Optional.none() : ancestor(scope, transform, stop));
13227
    };
13228
 
13229
    const isEq$3 = isEq$5;
13230
    const matchesUnInheritedFormatSelector = (ed, node, name) => {
13231
      const formatList = ed.formatter.get(name);
13232
      if (formatList) {
13233
        for (let i = 0; i < formatList.length; i++) {
13234
          const format = formatList[i];
13235
          if (isSelectorFormat(format) && format.inherit === false && ed.dom.is(node, format.selector)) {
13236
            return true;
13237
          }
13238
        }
13239
      }
13240
      return false;
13241
    };
13242
    const matchParents = (editor, node, name, vars, similar) => {
13243
      const root = editor.dom.getRoot();
13244
      if (node === root) {
13245
        return false;
13246
      }
13247
      const matchedNode = editor.dom.getParent(node, elm => {
13248
        if (matchesUnInheritedFormatSelector(editor, elm, name)) {
13249
          return true;
13250
        }
13251
        return elm.parentNode === root || !!matchNode(editor, elm, name, vars, true);
13252
      });
13253
      return !!matchNode(editor, matchedNode, name, vars, similar);
13254
    };
13255
    const matchName = (dom, node, format) => {
13256
      if (isInlineFormat(format) && isEq$3(node, format.inline)) {
13257
        return true;
13258
      }
13259
      if (isBlockFormat(format) && isEq$3(node, format.block)) {
13260
        return true;
13261
      }
13262
      if (isSelectorFormat(format)) {
13263
        return isElement$6(node) && dom.is(node, format.selector);
13264
      }
13265
      return false;
13266
    };
13267
    const matchItems = (dom, node, format, itemName, similar, vars) => {
13268
      const items = format[itemName];
13269
      const matchAttributes = itemName === 'attributes';
13270
      if (isFunction(format.onmatch)) {
13271
        return format.onmatch(node, format, itemName);
13272
      }
13273
      if (items) {
13274
        if (!isArrayLike(items)) {
13275
          for (const key in items) {
13276
            if (has$2(items, key)) {
13277
              const value = matchAttributes ? dom.getAttrib(node, key) : getStyle(dom, node, key);
13278
              const expectedValue = replaceVars(items[key], vars);
13279
              const isEmptyValue = isNullable(value) || isEmpty$3(value);
13280
              if (isEmptyValue && isNullable(expectedValue)) {
13281
                continue;
13282
              }
13283
              if (similar && isEmptyValue && !format.exact) {
13284
                return false;
13285
              }
13286
              if ((!similar || format.exact) && !isEq$3(value, normalizeStyleValue(expectedValue, key))) {
13287
                return false;
13288
              }
13289
            }
13290
          }
13291
        } else {
13292
          for (let i = 0; i < items.length; i++) {
13293
            if (matchAttributes ? dom.getAttrib(node, items[i]) : getStyle(dom, node, items[i])) {
13294
              return true;
13295
            }
13296
          }
13297
        }
13298
      }
13299
      return true;
13300
    };
13301
    const matchNode = (ed, node, name, vars, similar) => {
13302
      const formatList = ed.formatter.get(name);
13303
      const dom = ed.dom;
13304
      if (formatList && isElement$6(node)) {
13305
        for (let i = 0; i < formatList.length; i++) {
13306
          const format = formatList[i];
13307
          if (matchName(ed.dom, node, format) && matchItems(dom, node, format, 'attributes', similar, vars) && matchItems(dom, node, format, 'styles', similar, vars)) {
13308
            const classes = format.classes;
13309
            if (classes) {
13310
              for (let x = 0; x < classes.length; x++) {
13311
                if (!ed.dom.hasClass(node, replaceVars(classes[x], vars))) {
13312
                  return;
13313
                }
13314
              }
13315
            }
13316
            return format;
13317
          }
13318
        }
13319
      }
13320
      return undefined;
13321
    };
13322
    const match$2 = (editor, name, vars, node, similar) => {
13323
      if (node) {
13324
        return matchParents(editor, node, name, vars, similar);
13325
      }
13326
      node = editor.selection.getNode();
13327
      if (matchParents(editor, node, name, vars, similar)) {
13328
        return true;
13329
      }
13330
      const startNode = editor.selection.getStart();
13331
      if (startNode !== node) {
13332
        if (matchParents(editor, startNode, name, vars, similar)) {
13333
          return true;
13334
        }
13335
      }
13336
      return false;
13337
    };
13338
    const matchAll = (editor, names, vars) => {
13339
      const matchedFormatNames = [];
13340
      const checkedMap = {};
13341
      const startElement = editor.selection.getStart();
13342
      editor.dom.getParent(startElement, node => {
13343
        for (let i = 0; i < names.length; i++) {
13344
          const name = names[i];
13345
          if (!checkedMap[name] && matchNode(editor, node, name, vars)) {
13346
            checkedMap[name] = true;
13347
            matchedFormatNames.push(name);
13348
          }
13349
        }
13350
      }, editor.dom.getRoot());
13351
      return matchedFormatNames;
13352
    };
13353
    const closest = (editor, names) => {
13354
      const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody()));
13355
      const match = (elm, name) => matchNode(editor, elm.dom, name) ? Optional.some(name) : Optional.none();
13356
      return Optional.from(editor.selection.getStart(true)).bind(rawElm => closest$1(SugarElement.fromDom(rawElm), elm => findMap(names, name => match(elm, name)), isRoot)).getOrNull();
13357
    };
13358
    const canApply = (editor, name) => {
13359
      const formatList = editor.formatter.get(name);
13360
      const dom = editor.dom;
13361
      if (formatList && editor.selection.isEditable()) {
13362
        const startNode = editor.selection.getStart();
13363
        const parents = getParents$2(dom, startNode);
13364
        for (let x = formatList.length - 1; x >= 0; x--) {
13365
          const format = formatList[x];
13366
          if (!isSelectorFormat(format)) {
13367
            return true;
13368
          }
13369
          for (let i = parents.length - 1; i >= 0; i--) {
13370
            if (dom.is(parents[i], format.selector)) {
13371
              return true;
13372
            }
13373
          }
13374
        }
13375
      }
13376
      return false;
13377
    };
13378
    const matchAllOnNode = (editor, node, formatNames) => foldl(formatNames, (acc, name) => {
13379
      const matchSimilar = isVariableFormatName(editor, name);
13380
      if (editor.formatter.matchNode(node, name, {}, matchSimilar)) {
13381
        return acc.concat([name]);
13382
      } else {
13383
        return acc;
13384
      }
13385
    }, []);
13386
 
13387
    const ZWSP = ZWSP$1;
13388
    const importNode = (ownerDocument, node) => {
13389
      return ownerDocument.importNode(node, true);
13390
    };
13391
    const findFirstTextNode = node => {
13392
      if (node) {
13393
        const walker = new DomTreeWalker(node, node);
13394
        for (let tempNode = walker.current(); tempNode; tempNode = walker.next()) {
13395
          if (isText$a(tempNode)) {
13396
            return tempNode;
13397
          }
13398
        }
13399
      }
13400
      return null;
13401
    };
13402
    const createCaretContainer = fill => {
13403
      const caretContainer = SugarElement.fromTag('span');
13404
      setAll$1(caretContainer, {
13405
        'id': CARET_ID,
13406
        'data-mce-bogus': '1',
13407
        'data-mce-type': 'format-caret'
13408
      });
13409
      if (fill) {
13410
        append$1(caretContainer, SugarElement.fromText(ZWSP));
13411
      }
13412
      return caretContainer;
13413
    };
13414
    const trimZwspFromCaretContainer = caretContainerNode => {
13415
      const textNode = findFirstTextNode(caretContainerNode);
13416
      if (textNode && textNode.data.charAt(0) === ZWSP) {
13417
        textNode.deleteData(0, 1);
13418
      }
13419
      return textNode;
13420
    };
13421
    const removeCaretContainerNode = (editor, node, moveCaret) => {
13422
      const dom = editor.dom, selection = editor.selection;
13423
      if (isCaretContainerEmpty(node)) {
13424
        deleteElement$2(editor, false, SugarElement.fromDom(node), moveCaret, true);
13425
      } else {
13426
        const rng = selection.getRng();
13427
        const block = dom.getParent(node, dom.isBlock);
13428
        const startContainer = rng.startContainer;
13429
        const startOffset = rng.startOffset;
13430
        const endContainer = rng.endContainer;
13431
        const endOffset = rng.endOffset;
13432
        const textNode = trimZwspFromCaretContainer(node);
13433
        dom.remove(node, true);
13434
        if (startContainer === textNode && startOffset > 0) {
13435
          rng.setStart(textNode, startOffset - 1);
13436
        }
13437
        if (endContainer === textNode && endOffset > 0) {
13438
          rng.setEnd(textNode, endOffset - 1);
13439
        }
13440
        if (block && dom.isEmpty(block)) {
13441
          fillWithPaddingBr(SugarElement.fromDom(block));
13442
        }
13443
        selection.setRng(rng);
13444
      }
13445
    };
13446
    const removeCaretContainer = (editor, node, moveCaret) => {
13447
      const dom = editor.dom, selection = editor.selection;
13448
      if (!node) {
13449
        node = getParentCaretContainer(editor.getBody(), selection.getStart());
13450
        if (!node) {
13451
          while (node = dom.get(CARET_ID)) {
13452
            removeCaretContainerNode(editor, node, moveCaret);
13453
          }
13454
        }
13455
      } else {
13456
        removeCaretContainerNode(editor, node, moveCaret);
13457
      }
13458
    };
13459
    const insertCaretContainerNode = (editor, caretContainer, formatNode) => {
13460
      var _a, _b;
13461
      const dom = editor.dom;
13462
      const block = dom.getParent(formatNode, curry(isTextBlock$1, editor.schema));
13463
      if (block && dom.isEmpty(block)) {
13464
        (_a = formatNode.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(caretContainer, formatNode);
13465
      } else {
13466
        removeTrailingBr(SugarElement.fromDom(formatNode));
13467
        if (dom.isEmpty(formatNode)) {
13468
          (_b = formatNode.parentNode) === null || _b === void 0 ? void 0 : _b.replaceChild(caretContainer, formatNode);
13469
        } else {
13470
          dom.insertAfter(caretContainer, formatNode);
13471
        }
13472
      }
13473
    };
13474
    const appendNode = (parentNode, node) => {
13475
      parentNode.appendChild(node);
13476
      return node;
13477
    };
13478
    const insertFormatNodesIntoCaretContainer = (formatNodes, caretContainer) => {
13479
      var _a;
13480
      const innerMostFormatNode = foldr(formatNodes, (parentNode, formatNode) => {
13481
        return appendNode(parentNode, formatNode.cloneNode(false));
13482
      }, caretContainer);
13483
      const doc = (_a = innerMostFormatNode.ownerDocument) !== null && _a !== void 0 ? _a : document;
13484
      return appendNode(innerMostFormatNode, doc.createTextNode(ZWSP));
13485
    };
13486
    const cleanFormatNode = (editor, caretContainer, formatNode, name, vars, similar) => {
13487
      const formatter = editor.formatter;
13488
      const dom = editor.dom;
13489
      const validFormats = filter$5(keys(formatter.get()), formatName => formatName !== name && !contains$1(formatName, 'removeformat'));
13490
      const matchedFormats = matchAllOnNode(editor, formatNode, validFormats);
13491
      const uniqueFormats = filter$5(matchedFormats, fmtName => !areSimilarFormats(editor, fmtName, name));
13492
      if (uniqueFormats.length > 0) {
13493
        const clonedFormatNode = formatNode.cloneNode(false);
13494
        dom.add(caretContainer, clonedFormatNode);
13495
        formatter.remove(name, vars, clonedFormatNode, similar);
13496
        dom.remove(clonedFormatNode);
13497
        return Optional.some(clonedFormatNode);
13498
      } else {
13499
        return Optional.none();
13500
      }
13501
    };
13502
    const applyCaretFormat = (editor, name, vars) => {
13503
      let caretContainer;
13504
      const selection = editor.selection;
13505
      const formatList = editor.formatter.get(name);
13506
      if (!formatList) {
13507
        return;
13508
      }
13509
      const selectionRng = selection.getRng();
13510
      let offset = selectionRng.startOffset;
13511
      const container = selectionRng.startContainer;
13512
      const text = container.nodeValue;
13513
      caretContainer = getParentCaretContainer(editor.getBody(), selection.getStart());
13514
      const wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/;
13515
      if (text && offset > 0 && offset < text.length && wordcharRegex.test(text.charAt(offset)) && wordcharRegex.test(text.charAt(offset - 1))) {
13516
        const bookmark = selection.getBookmark();
13517
        selectionRng.collapse(true);
13518
        let rng = expandRng(editor.dom, selectionRng, formatList);
13519
        rng = split(rng);
13520
        editor.formatter.apply(name, vars, rng);
13521
        selection.moveToBookmark(bookmark);
13522
      } else {
13523
        let textNode = caretContainer ? findFirstTextNode(caretContainer) : null;
13524
        if (!caretContainer || (textNode === null || textNode === void 0 ? void 0 : textNode.data) !== ZWSP) {
13525
          caretContainer = importNode(editor.getDoc(), createCaretContainer(true).dom);
13526
          textNode = caretContainer.firstChild;
13527
          selectionRng.insertNode(caretContainer);
13528
          offset = 1;
13529
          editor.formatter.apply(name, vars, caretContainer);
13530
        } else {
13531
          editor.formatter.apply(name, vars, caretContainer);
13532
        }
13533
        selection.setCursorLocation(textNode, offset);
13534
      }
13535
    };
13536
    const removeCaretFormat = (editor, name, vars, similar) => {
13537
      const dom = editor.dom;
13538
      const selection = editor.selection;
13539
      let hasContentAfter = false;
13540
      const formatList = editor.formatter.get(name);
13541
      if (!formatList) {
13542
        return;
13543
      }
13544
      const rng = selection.getRng();
13545
      const container = rng.startContainer;
13546
      const offset = rng.startOffset;
13547
      let node = container;
13548
      if (isText$a(container)) {
13549
        if (offset !== container.data.length) {
13550
          hasContentAfter = true;
13551
        }
13552
        node = node.parentNode;
13553
      }
13554
      const parents = [];
13555
      let formatNode;
13556
      while (node) {
13557
        if (matchNode(editor, node, name, vars, similar)) {
13558
          formatNode = node;
13559
          break;
13560
        }
13561
        if (node.nextSibling) {
13562
          hasContentAfter = true;
13563
        }
13564
        parents.push(node);
13565
        node = node.parentNode;
13566
      }
13567
      if (!formatNode) {
13568
        return;
13569
      }
13570
      if (hasContentAfter) {
13571
        const bookmark = selection.getBookmark();
13572
        rng.collapse(true);
13573
        let expandedRng = expandRng(dom, rng, formatList, true);
13574
        expandedRng = split(expandedRng);
13575
        editor.formatter.remove(name, vars, expandedRng, similar);
13576
        selection.moveToBookmark(bookmark);
13577
      } else {
13578
        const caretContainer = getParentCaretContainer(editor.getBody(), formatNode);
13579
        const parentsAfter = isNonNullable(caretContainer) ? dom.getParents(formatNode.parentNode, always, caretContainer) : [];
13580
        const newCaretContainer = createCaretContainer(false).dom;
13581
        insertCaretContainerNode(editor, newCaretContainer, caretContainer !== null && caretContainer !== void 0 ? caretContainer : formatNode);
13582
        const cleanedFormatNode = cleanFormatNode(editor, newCaretContainer, formatNode, name, vars, similar);
13583
        const caretTextNode = insertFormatNodesIntoCaretContainer([
13584
          ...parents,
13585
          ...cleanedFormatNode.toArray(),
13586
          ...parentsAfter
13587
        ], newCaretContainer);
13588
        if (caretContainer) {
13589
          removeCaretContainerNode(editor, caretContainer, isNonNullable(caretContainer));
13590
        }
13591
        selection.setCursorLocation(caretTextNode, 1);
13592
        if (dom.isEmpty(formatNode)) {
13593
          dom.remove(formatNode);
13594
        }
13595
      }
13596
    };
13597
    const disableCaretContainer = (editor, keyCode, moveCaret) => {
13598
      const selection = editor.selection, body = editor.getBody();
13599
      removeCaretContainer(editor, null, moveCaret);
13600
      if ((keyCode === 8 || keyCode === 46) && selection.isCollapsed() && selection.getStart().innerHTML === ZWSP) {
13601
        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()), true);
13602
      }
13603
      if (keyCode === 37 || keyCode === 39) {
13604
        removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()), true);
13605
      }
13606
    };
13607
    const endsWithNbsp = element => isText$a(element) && endsWith(element.data, nbsp);
13608
    const setup$v = editor => {
13609
      editor.on('mouseup keydown', e => {
13610
        disableCaretContainer(editor, e.keyCode, endsWithNbsp(editor.selection.getRng().endContainer));
13611
      });
13612
    };
13613
    const createCaretFormat = formatNodes => {
13614
      const caretContainer = createCaretContainer(false);
13615
      const innerMost = insertFormatNodesIntoCaretContainer(formatNodes, caretContainer.dom);
13616
      return {
13617
        caretContainer,
13618
        caretPosition: CaretPosition(innerMost, 0)
13619
      };
13620
    };
13621
    const replaceWithCaretFormat = (targetNode, formatNodes) => {
13622
      const {caretContainer, caretPosition} = createCaretFormat(formatNodes);
13623
      before$3(SugarElement.fromDom(targetNode), caretContainer);
13624
      remove$5(SugarElement.fromDom(targetNode));
13625
      return caretPosition;
13626
    };
13627
    const createCaretFormatAtStart$1 = (rng, formatNodes) => {
13628
      const {caretContainer, caretPosition} = createCaretFormat(formatNodes);
13629
      rng.insertNode(caretContainer.dom);
13630
      return caretPosition;
13631
    };
13632
    const isFormatElement = (editor, element) => {
13633
      if (isCaretNode(element.dom)) {
13634
        return false;
13635
      }
13636
      const inlineElements = editor.schema.getTextInlineElements();
13637
      return has$2(inlineElements, name(element)) && !isCaretNode(element.dom) && !isBogus$2(element.dom);
13638
    };
13639
 
13640
    const postProcessHooks = {};
13641
    const isPre = matchNodeNames(['pre']);
13642
    const addPostProcessHook = (name, hook) => {
13643
      const hooks = postProcessHooks[name];
13644
      if (!hooks) {
13645
        postProcessHooks[name] = [];
13646
      }
13647
      postProcessHooks[name].push(hook);
13648
    };
13649
    const postProcess$1 = (name, editor) => {
13650
      if (has$2(postProcessHooks, name)) {
13651
        each$e(postProcessHooks[name], hook => {
13652
          hook(editor);
13653
        });
13654
      }
13655
    };
13656
    addPostProcessHook('pre', editor => {
13657
      const rng = editor.selection.getRng();
13658
      const hasPreSibling = blocks => pre => {
13659
        const prev = pre.previousSibling;
13660
        return isPre(prev) && contains$2(blocks, prev);
13661
      };
13662
      const joinPre = (pre1, pre2) => {
13663
        const sPre2 = SugarElement.fromDom(pre2);
13664
        const doc = documentOrOwner(sPre2).dom;
13665
        remove$5(sPre2);
13666
        append(SugarElement.fromDom(pre1), [
13667
          SugarElement.fromTag('br', doc),
13668
          SugarElement.fromTag('br', doc),
13669
          ...children$1(sPre2)
13670
        ]);
13671
      };
13672
      if (!rng.collapsed) {
13673
        const blocks = editor.selection.getSelectedBlocks();
13674
        const preBlocks = filter$5(filter$5(blocks, isPre), hasPreSibling(blocks));
13675
        each$e(preBlocks, pre => {
13676
          joinPre(pre.previousSibling, pre);
13677
        });
13678
      }
13679
    });
13680
 
13681
    const listItemStyles = [
13682
      'fontWeight',
13683
      'fontStyle',
13684
      'color',
13685
      'fontSize',
13686
      'fontFamily'
13687
    ];
13688
    const hasListStyles = fmt => isObject(fmt.styles) && exists(keys(fmt.styles), name => contains$2(listItemStyles, name));
13689
    const findExpandedListItemFormat = formats => find$2(formats, fmt => isInlineFormat(fmt) && fmt.inline === 'span' && hasListStyles(fmt));
13690
    const getExpandedListItemFormat = (formatter, format) => {
13691
      const formatList = formatter.get(format);
13692
      return isArray$1(formatList) ? findExpandedListItemFormat(formatList) : Optional.none();
13693
    };
13694
    const isRngStartAtStartOfElement = (rng, elm) => prevPosition(elm, CaretPosition.fromRangeStart(rng)).isNone();
13695
    const isRngEndAtEndOfElement = (rng, elm) => {
13696
      return nextPosition(elm, CaretPosition.fromRangeEnd(rng)).exists(pos => !isBr$6(pos.getNode()) || nextPosition(elm, pos).isSome()) === false;
13697
    };
13698
    const isEditableListItem = dom => elm => isListItem$2(elm) && dom.isEditable(elm);
13699
    const getFullySelectedBlocks = selection => {
13700
      const blocks = selection.getSelectedBlocks();
13701
      const rng = selection.getRng();
13702
      if (selection.isCollapsed()) {
13703
        return [];
13704
      }
13705
      if (blocks.length === 1) {
13706
        return isRngStartAtStartOfElement(rng, blocks[0]) && isRngEndAtEndOfElement(rng, blocks[0]) ? blocks : [];
13707
      } else {
13708
        const first = head(blocks).filter(elm => isRngStartAtStartOfElement(rng, elm)).toArray();
13709
        const last = last$3(blocks).filter(elm => isRngEndAtEndOfElement(rng, elm)).toArray();
13710
        const middle = blocks.slice(1, -1);
13711
        return first.concat(middle).concat(last);
13712
      }
13713
    };
13714
    const getFullySelectedListItems = selection => filter$5(getFullySelectedBlocks(selection), isEditableListItem(selection.dom));
13715
    const getPartiallySelectedListItems = selection => filter$5(selection.getSelectedBlocks(), isEditableListItem(selection.dom));
13716
 
13717
    const each$8 = Tools.each;
13718
    const isElementNode = node => isElement$6(node) && !isBookmarkNode$1(node) && !isCaretNode(node) && !isBogus$2(node);
13719
    const findElementSibling = (node, siblingName) => {
13720
      for (let sibling = node; sibling; sibling = sibling[siblingName]) {
13721
        if (isText$a(sibling) && isNotEmpty(sibling.data)) {
13722
          return node;
13723
        }
13724
        if (isElement$6(sibling) && !isBookmarkNode$1(sibling)) {
13725
          return sibling;
13726
        }
13727
      }
13728
      return node;
13729
    };
13730
    const mergeSiblingsNodes = (editor, prev, next) => {
13731
      const elementUtils = ElementUtils(editor);
13732
      const isPrevEditable = isHTMLElement(prev) && editor.dom.isEditable(prev);
13733
      const isNextEditable = isHTMLElement(next) && editor.dom.isEditable(next);
13734
      if (isPrevEditable && isNextEditable) {
13735
        const prevSibling = findElementSibling(prev, 'previousSibling');
13736
        const nextSibling = findElementSibling(next, 'nextSibling');
13737
        if (elementUtils.compare(prevSibling, nextSibling)) {
13738
          for (let sibling = prevSibling.nextSibling; sibling && sibling !== nextSibling;) {
13739
            const tmpSibling = sibling;
13740
            sibling = sibling.nextSibling;
13741
            prevSibling.appendChild(tmpSibling);
13742
          }
13743
          editor.dom.remove(nextSibling);
13744
          Tools.each(Tools.grep(nextSibling.childNodes), node => {
13745
            prevSibling.appendChild(node);
13746
          });
13747
          return prevSibling;
13748
        }
13749
      }
13750
      return next;
13751
    };
13752
    const mergeSiblings = (editor, format, vars, node) => {
13753
      var _a;
13754
      if (node && format.merge_siblings !== false) {
13755
        const newNode = (_a = mergeSiblingsNodes(editor, getNonWhiteSpaceSibling(node), node)) !== null && _a !== void 0 ? _a : node;
13756
        mergeSiblingsNodes(editor, newNode, getNonWhiteSpaceSibling(newNode, true));
13757
      }
13758
    };
13759
    const clearChildStyles = (dom, format, node) => {
13760
      if (format.clear_child_styles) {
13761
        const selector = format.links ? '*:not(a)' : '*';
13762
        each$8(dom.select(selector, node), childNode => {
13763
          if (isElementNode(childNode) && dom.isEditable(childNode)) {
13764
            each$8(format.styles, (_value, name) => {
13765
              dom.setStyle(childNode, name, '');
13766
            });
13767
          }
13768
        });
13769
      }
13770
    };
13771
    const processChildElements = (node, filter, process) => {
13772
      each$8(node.childNodes, node => {
13773
        if (isElementNode(node)) {
13774
          if (filter(node)) {
13775
            process(node);
13776
          }
13777
          if (node.hasChildNodes()) {
13778
            processChildElements(node, filter, process);
13779
          }
13780
        }
13781
      });
13782
    };
13783
    const unwrapEmptySpan = (dom, node) => {
13784
      if (node.nodeName === 'SPAN' && dom.getAttribs(node).length === 0) {
13785
        dom.remove(node, true);
13786
      }
13787
    };
13788
    const hasStyle = (dom, name) => node => !!(node && getStyle(dom, node, name));
13789
    const applyStyle = (dom, name, value) => node => {
13790
      dom.setStyle(node, name, value);
13791
      if (node.getAttribute('style') === '') {
13792
        node.removeAttribute('style');
13793
      }
13794
      unwrapEmptySpan(dom, node);
13795
    };
13796
 
13797
    const removeResult = Adt.generate([
13798
      { keep: [] },
13799
      { rename: ['name'] },
13800
      { removed: [] }
13801
    ]);
13802
    const MCE_ATTR_RE = /^(src|href|style)$/;
13803
    const each$7 = Tools.each;
13804
    const isEq$2 = isEq$5;
13805
    const isTableCellOrRow = node => /^(TR|TH|TD)$/.test(node.nodeName);
13806
    const isChildOfInlineParent = (dom, node, parent) => dom.isChildOf(node, parent) && node !== parent && !dom.isBlock(parent);
13807
    const getContainer = (ed, rng, start) => {
13808
      let container = rng[start ? 'startContainer' : 'endContainer'];
13809
      let offset = rng[start ? 'startOffset' : 'endOffset'];
13810
      if (isElement$6(container)) {
13811
        const lastIdx = container.childNodes.length - 1;
13812
        if (!start && offset) {
13813
          offset--;
13814
        }
13815
        container = container.childNodes[offset > lastIdx ? lastIdx : offset];
13816
      }
13817
      if (isText$a(container) && start && offset >= container.data.length) {
13818
        container = new DomTreeWalker(container, ed.getBody()).next() || container;
13819
      }
13820
      if (isText$a(container) && !start && offset === 0) {
13821
        container = new DomTreeWalker(container, ed.getBody()).prev() || container;
13822
      }
13823
      return container;
13824
    };
13825
    const normalizeTableSelection = (node, start) => {
13826
      const prop = start ? 'firstChild' : 'lastChild';
13827
      const childNode = node[prop];
13828
      if (isTableCellOrRow(node) && childNode) {
13829
        if (node.nodeName === 'TR') {
13830
          return childNode[prop] || childNode;
13831
        } else {
13832
          return childNode;
13833
        }
13834
      }
13835
      return node;
13836
    };
13837
    const wrap$1 = (dom, node, name, attrs) => {
13838
      var _a;
13839
      const wrapper = dom.create(name, attrs);
13840
      (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(wrapper, node);
13841
      wrapper.appendChild(node);
13842
      return wrapper;
13843
    };
13844
    const wrapWithSiblings = (dom, node, next, name, attrs) => {
13845
      const start = SugarElement.fromDom(node);
13846
      const wrapper = SugarElement.fromDom(dom.create(name, attrs));
13847
      const siblings = next ? nextSiblings(start) : prevSiblings(start);
13848
      append(wrapper, siblings);
13849
      if (next) {
13850
        before$3(start, wrapper);
13851
        prepend(wrapper, start);
13852
      } else {
13853
        after$4(start, wrapper);
13854
        append$1(wrapper, start);
13855
      }
13856
      return wrapper.dom;
13857
    };
13858
    const isColorFormatAndAnchor = (node, format) => format.links && node.nodeName === 'A';
13859
    const removeNode = (ed, node, format) => {
13860
      const parentNode = node.parentNode;
13861
      let rootBlockElm;
13862
      const dom = ed.dom;
13863
      const forcedRootBlock = getForcedRootBlock(ed);
13864
      if (isBlockFormat(format)) {
13865
        if (parentNode === dom.getRoot()) {
13866
          if (!format.list_block || !isEq$2(node, format.list_block)) {
13867
            each$e(from(node.childNodes), node => {
13868
              if (isValid(ed, forcedRootBlock, node.nodeName.toLowerCase())) {
13869
                if (!rootBlockElm) {
13870
                  rootBlockElm = wrap$1(dom, node, forcedRootBlock);
13871
                  dom.setAttribs(rootBlockElm, getForcedRootBlockAttrs(ed));
13872
                } else {
13873
                  rootBlockElm.appendChild(node);
13874
                }
13875
              } else {
13876
                rootBlockElm = null;
13877
              }
13878
            });
13879
          }
13880
        }
13881
      }
13882
      if (isMixedFormat(format) && !isEq$2(format.inline, node)) {
13883
        return;
13884
      }
13885
      dom.remove(node, true);
13886
    };
13887
    const processFormatAttrOrStyle = (name, value, vars) => {
13888
      if (isNumber(name)) {
13889
        return {
13890
          name: value,
13891
          value: null
13892
        };
13893
      } else {
13894
        return {
13895
          name,
13896
          value: replaceVars(value, vars)
13897
        };
13898
      }
13899
    };
13900
    const removeEmptyStyleAttributeIfNeeded = (dom, elm) => {
13901
      if (dom.getAttrib(elm, 'style') === '') {
13902
        elm.removeAttribute('style');
13903
        elm.removeAttribute('data-mce-style');
13904
      }
13905
    };
13906
    const removeStyles = (dom, elm, format, vars, compareNode) => {
13907
      let stylesModified = false;
13908
      each$7(format.styles, (value, name) => {
13909
        const {
13910
          name: styleName,
13911
          value: styleValue
13912
        } = processFormatAttrOrStyle(name, value, vars);
13913
        const normalizedStyleValue = normalizeStyleValue(styleValue, styleName);
13914
        if (format.remove_similar || isNull(styleValue) || !isElement$6(compareNode) || isEq$2(getStyle(dom, compareNode, styleName), normalizedStyleValue)) {
13915
          dom.setStyle(elm, styleName, '');
13916
        }
13917
        stylesModified = true;
13918
      });
13919
      if (stylesModified) {
13920
        removeEmptyStyleAttributeIfNeeded(dom, elm);
13921
      }
13922
    };
13923
    const removeListStyleFormats = (editor, name, vars) => {
13924
      if (name === 'removeformat') {
13925
        each$e(getPartiallySelectedListItems(editor.selection), li => {
13926
          each$e(listItemStyles, name => editor.dom.setStyle(li, name, ''));
13927
          removeEmptyStyleAttributeIfNeeded(editor.dom, li);
13928
        });
13929
      } else {
13930
        getExpandedListItemFormat(editor.formatter, name).each(liFmt => {
13931
          each$e(getPartiallySelectedListItems(editor.selection), li => removeStyles(editor.dom, li, liFmt, vars, null));
13932
        });
13933
      }
13934
    };
13935
    const removeNodeFormatInternal = (ed, format, vars, node, compareNode) => {
13936
      const dom = ed.dom;
13937
      const elementUtils = ElementUtils(ed);
13938
      const schema = ed.schema;
13939
      if (isInlineFormat(format) && isTransparentElementName(schema, format.inline) && isTransparentBlock(schema, node) && node.parentElement === ed.getBody()) {
13940
        removeNode(ed, node, format);
13941
        return removeResult.removed();
13942
      }
13943
      if (!format.ceFalseOverride && node && dom.getContentEditableParent(node) === 'false') {
13944
        return removeResult.keep();
13945
      }
13946
      if (node && !matchName(dom, node, format) && !isColorFormatAndAnchor(node, format)) {
13947
        return removeResult.keep();
13948
      }
13949
      const elm = node;
13950
      const preserveAttributes = format.preserve_attributes;
13951
      if (isInlineFormat(format) && format.remove === 'all' && isArray$1(preserveAttributes)) {
13952
        const attrsToPreserve = filter$5(dom.getAttribs(elm), attr => contains$2(preserveAttributes, attr.name.toLowerCase()));
13953
        dom.removeAllAttribs(elm);
13954
        each$e(attrsToPreserve, attr => dom.setAttrib(elm, attr.name, attr.value));
13955
        if (attrsToPreserve.length > 0) {
13956
          return removeResult.rename('span');
13957
        }
13958
      }
13959
      if (format.remove !== 'all') {
13960
        removeStyles(dom, elm, format, vars, compareNode);
13961
        each$7(format.attributes, (value, name) => {
13962
          const {
13963
            name: attrName,
13964
            value: attrValue
13965
          } = processFormatAttrOrStyle(name, value, vars);
13966
          if (format.remove_similar || isNull(attrValue) || !isElement$6(compareNode) || isEq$2(dom.getAttrib(compareNode, attrName), attrValue)) {
13967
            if (attrName === 'class') {
13968
              const currentValue = dom.getAttrib(elm, attrName);
13969
              if (currentValue) {
13970
                let valueOut = '';
13971
                each$e(currentValue.split(/\s+/), cls => {
13972
                  if (/mce\-\w+/.test(cls)) {
13973
                    valueOut += (valueOut ? ' ' : '') + cls;
13974
                  }
13975
                });
13976
                if (valueOut) {
13977
                  dom.setAttrib(elm, attrName, valueOut);
13978
                  return;
13979
                }
13980
              }
13981
            }
13982
            if (MCE_ATTR_RE.test(attrName)) {
13983
              elm.removeAttribute('data-mce-' + attrName);
13984
            }
13985
            if (attrName === 'style' && matchNodeNames(['li'])(elm) && dom.getStyle(elm, 'list-style-type') === 'none') {
13986
              elm.removeAttribute(attrName);
13987
              dom.setStyle(elm, 'list-style-type', 'none');
13988
              return;
13989
            }
13990
            if (attrName === 'class') {
13991
              elm.removeAttribute('className');
13992
            }
13993
            elm.removeAttribute(attrName);
13994
          }
13995
        });
13996
        each$7(format.classes, value => {
13997
          value = replaceVars(value, vars);
13998
          if (!isElement$6(compareNode) || dom.hasClass(compareNode, value)) {
13999
            dom.removeClass(elm, value);
14000
          }
14001
        });
14002
        const attrs = dom.getAttribs(elm);
14003
        for (let i = 0; i < attrs.length; i++) {
14004
          const attrName = attrs[i].nodeName;
14005
          if (!elementUtils.isAttributeInternal(attrName)) {
14006
            return removeResult.keep();
14007
          }
14008
        }
14009
      }
14010
      if (format.remove !== 'none') {
14011
        removeNode(ed, elm, format);
14012
        return removeResult.removed();
14013
      }
14014
      return removeResult.keep();
14015
    };
14016
    const findFormatRoot = (editor, container, name, vars, similar) => {
14017
      let formatRoot;
14018
      if (container.parentNode) {
14019
        each$e(getParents$2(editor.dom, container.parentNode).reverse(), parent => {
14020
          if (!formatRoot && isElement$6(parent) && parent.id !== '_start' && parent.id !== '_end') {
14021
            const format = matchNode(editor, parent, name, vars, similar);
14022
            if (format && format.split !== false) {
14023
              formatRoot = parent;
14024
            }
14025
          }
14026
        });
14027
      }
14028
      return formatRoot;
14029
    };
14030
    const removeNodeFormatFromClone = (editor, format, vars, clone) => removeNodeFormatInternal(editor, format, vars, clone, clone).fold(constant(clone), newName => {
14031
      const fragment = editor.dom.createFragment();
14032
      fragment.appendChild(clone);
14033
      return editor.dom.rename(clone, newName);
14034
    }, constant(null));
14035
    const wrapAndSplit = (editor, formatList, formatRoot, container, target, split, format, vars) => {
14036
      var _a, _b;
14037
      let lastClone;
14038
      let firstClone;
14039
      const dom = editor.dom;
14040
      if (formatRoot) {
14041
        const formatRootParent = formatRoot.parentNode;
14042
        for (let parent = container.parentNode; parent && parent !== formatRootParent; parent = parent.parentNode) {
14043
          let clone = dom.clone(parent, false);
14044
          for (let i = 0; i < formatList.length; i++) {
14045
            clone = removeNodeFormatFromClone(editor, formatList[i], vars, clone);
14046
            if (clone === null) {
14047
              break;
14048
            }
14049
          }
14050
          if (clone) {
14051
            if (lastClone) {
14052
              clone.appendChild(lastClone);
14053
            }
14054
            if (!firstClone) {
14055
              firstClone = clone;
14056
            }
14057
            lastClone = clone;
14058
          }
14059
        }
14060
        if (split && (!format.mixed || !dom.isBlock(formatRoot))) {
14061
          container = (_a = dom.split(formatRoot, container)) !== null && _a !== void 0 ? _a : container;
14062
        }
14063
        if (lastClone && firstClone) {
14064
          (_b = target.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(lastClone, target);
14065
          firstClone.appendChild(target);
14066
          if (isInlineFormat(format)) {
14067
            mergeSiblings(editor, format, vars, lastClone);
14068
          }
14069
        }
14070
      }
14071
      return container;
14072
    };
14073
    const removeFormatInternal = (ed, name, vars, node, similar) => {
14074
      const formatList = ed.formatter.get(name);
14075
      const format = formatList[0];
14076
      const dom = ed.dom;
14077
      const selection = ed.selection;
14078
      const splitToFormatRoot = container => {
14079
        const formatRoot = findFormatRoot(ed, container, name, vars, similar);
14080
        return wrapAndSplit(ed, formatList, formatRoot, container, container, true, format, vars);
14081
      };
14082
      const isRemoveBookmarkNode = node => isBookmarkNode$1(node) && isElement$6(node) && (node.id === '_start' || node.id === '_end');
14083
      const removeFormatOnNode = node => exists(formatList, fmt => removeNodeFormat(ed, fmt, vars, node, node));
14084
      const process = node => {
14085
        const children = from(node.childNodes);
14086
        const removed = removeFormatOnNode(node);
14087
        const currentNodeMatches = removed || exists(formatList, f => matchName(dom, node, f));
14088
        const parentNode = node.parentNode;
14089
        if (!currentNodeMatches && isNonNullable(parentNode) && shouldExpandToSelector(format)) {
14090
          removeFormatOnNode(parentNode);
14091
        }
14092
        if (format.deep) {
14093
          if (children.length) {
14094
            for (let i = 0; i < children.length; i++) {
14095
              process(children[i]);
14096
            }
14097
          }
14098
        }
14099
        const textDecorations = [
14100
          'underline',
14101
          'line-through',
14102
          'overline'
14103
        ];
14104
        each$e(textDecorations, decoration => {
14105
          if (isElement$6(node) && ed.dom.getStyle(node, 'text-decoration') === decoration && node.parentNode && getTextDecoration(dom, node.parentNode) === decoration) {
14106
            removeNodeFormat(ed, {
14107
              deep: false,
14108
              exact: true,
14109
              inline: 'span',
14110
              styles: { textDecoration: decoration }
14111
            }, undefined, node);
14112
          }
14113
        });
14114
      };
14115
      const unwrap = start => {
14116
        const node = dom.get(start ? '_start' : '_end');
14117
        if (node) {
14118
          let out = node[start ? 'firstChild' : 'lastChild'];
14119
          if (isRemoveBookmarkNode(out)) {
14120
            out = out[start ? 'firstChild' : 'lastChild'];
14121
          }
14122
          if (isText$a(out) && out.data.length === 0) {
14123
            out = start ? node.previousSibling || node.nextSibling : node.nextSibling || node.previousSibling;
14124
          }
14125
          dom.remove(node, true);
14126
          return out;
14127
        } else {
14128
          return null;
14129
        }
14130
      };
14131
      const removeRngStyle = rng => {
14132
        let startContainer;
14133
        let endContainer;
14134
        let expandedRng = expandRng(dom, rng, formatList, rng.collapsed);
14135
        if (format.split) {
14136
          expandedRng = split(expandedRng);
14137
          startContainer = getContainer(ed, expandedRng, true);
14138
          endContainer = getContainer(ed, expandedRng);
14139
          if (startContainer !== endContainer) {
14140
            startContainer = normalizeTableSelection(startContainer, true);
14141
            endContainer = normalizeTableSelection(endContainer, false);
14142
            if (isChildOfInlineParent(dom, startContainer, endContainer)) {
14143
              const marker = Optional.from(startContainer.firstChild).getOr(startContainer);
14144
              splitToFormatRoot(wrapWithSiblings(dom, marker, true, 'span', {
14145
                'id': '_start',
14146
                'data-mce-type': 'bookmark'
14147
              }));
14148
              unwrap(true);
14149
              return;
14150
            }
14151
            if (isChildOfInlineParent(dom, endContainer, startContainer)) {
14152
              const marker = Optional.from(endContainer.lastChild).getOr(endContainer);
14153
              splitToFormatRoot(wrapWithSiblings(dom, marker, false, 'span', {
14154
                'id': '_end',
14155
                'data-mce-type': 'bookmark'
14156
              }));
14157
              unwrap(false);
14158
              return;
14159
            }
14160
            startContainer = wrap$1(dom, startContainer, 'span', {
14161
              'id': '_start',
14162
              'data-mce-type': 'bookmark'
14163
            });
14164
            endContainer = wrap$1(dom, endContainer, 'span', {
14165
              'id': '_end',
14166
              'data-mce-type': 'bookmark'
14167
            });
14168
            const newRng = dom.createRng();
14169
            newRng.setStartAfter(startContainer);
14170
            newRng.setEndBefore(endContainer);
14171
            walk$3(dom, newRng, nodes => {
14172
              each$e(nodes, n => {
14173
                if (!isBookmarkNode$1(n) && !isBookmarkNode$1(n.parentNode)) {
14174
                  splitToFormatRoot(n);
14175
                }
14176
              });
14177
            });
14178
            splitToFormatRoot(startContainer);
14179
            splitToFormatRoot(endContainer);
14180
            startContainer = unwrap(true);
14181
            endContainer = unwrap();
14182
          } else {
14183
            startContainer = endContainer = splitToFormatRoot(startContainer);
14184
          }
14185
          expandedRng.startContainer = startContainer.parentNode ? startContainer.parentNode : startContainer;
14186
          expandedRng.startOffset = dom.nodeIndex(startContainer);
14187
          expandedRng.endContainer = endContainer.parentNode ? endContainer.parentNode : endContainer;
14188
          expandedRng.endOffset = dom.nodeIndex(endContainer) + 1;
14189
        }
14190
        walk$3(dom, expandedRng, nodes => {
14191
          each$e(nodes, process);
14192
        });
14193
      };
14194
      if (node) {
14195
        if (isNode(node)) {
14196
          const rng = dom.createRng();
14197
          rng.setStartBefore(node);
14198
          rng.setEndAfter(node);
14199
          removeRngStyle(rng);
14200
        } else {
14201
          removeRngStyle(node);
14202
        }
14203
        fireFormatRemove(ed, name, node, vars);
14204
        return;
14205
      }
14206
      if (!selection.isCollapsed() || !isInlineFormat(format) || getCellsFromEditor(ed).length) {
14207
        preserveSelection(ed, () => runOnRanges(ed, removeRngStyle), startNode => isInlineFormat(format) && match$2(ed, name, vars, startNode));
14208
        ed.nodeChanged();
14209
      } else {
14210
        removeCaretFormat(ed, name, vars, similar);
14211
      }
14212
      removeListStyleFormats(ed, name, vars);
14213
      fireFormatRemove(ed, name, node, vars);
14214
    };
14215
    const removeFormat$1 = (ed, name, vars, node, similar) => {
14216
      if (node || ed.selection.isEditable()) {
14217
        removeFormatInternal(ed, name, vars, node, similar);
14218
      }
14219
    };
14220
    const removeNodeFormat = (editor, format, vars, node, compareNode) => {
14221
      return removeNodeFormatInternal(editor, format, vars, node, compareNode).fold(never, newName => {
14222
        editor.dom.rename(node, newName);
14223
        return true;
14224
      }, always);
14225
    };
14226
 
14227
    const each$6 = Tools.each;
14228
    const mergeTextDecorationsAndColor = (dom, format, vars, node) => {
14229
      const processTextDecorationsAndColor = n => {
14230
        if (isHTMLElement(n) && isElement$6(n.parentNode) && dom.isEditable(n)) {
14231
          const parentTextDecoration = getTextDecoration(dom, n.parentNode);
14232
          if (dom.getStyle(n, 'color') && parentTextDecoration) {
14233
            dom.setStyle(n, 'text-decoration', parentTextDecoration);
14234
          } else if (dom.getStyle(n, 'text-decoration') === parentTextDecoration) {
14235
            dom.setStyle(n, 'text-decoration', null);
14236
          }
14237
        }
14238
      };
14239
      if (format.styles && (format.styles.color || format.styles.textDecoration)) {
14240
        Tools.walk(node, processTextDecorationsAndColor, 'childNodes');
14241
        processTextDecorationsAndColor(node);
14242
      }
14243
    };
14244
    const mergeBackgroundColorAndFontSize = (dom, format, vars, node) => {
14245
      if (format.styles && format.styles.backgroundColor) {
14246
        const hasFontSize = hasStyle(dom, 'fontSize');
14247
        processChildElements(node, elm => hasFontSize(elm) && dom.isEditable(elm), applyStyle(dom, 'backgroundColor', replaceVars(format.styles.backgroundColor, vars)));
14248
      }
14249
    };
14250
    const mergeSubSup = (dom, format, vars, node) => {
14251
      if (isInlineFormat(format) && (format.inline === 'sub' || format.inline === 'sup')) {
14252
        const hasFontSize = hasStyle(dom, 'fontSize');
14253
        processChildElements(node, elm => hasFontSize(elm) && dom.isEditable(elm), applyStyle(dom, 'fontSize', ''));
14254
        const inverseTagDescendants = filter$5(dom.select(format.inline === 'sup' ? 'sub' : 'sup', node), dom.isEditable);
14255
        dom.remove(inverseTagDescendants, true);
14256
      }
14257
    };
14258
    const mergeWithChildren = (editor, formatList, vars, node) => {
14259
      each$6(formatList, format => {
14260
        if (isInlineFormat(format)) {
14261
          each$6(editor.dom.select(format.inline, node), child => {
14262
            if (isElementNode(child)) {
14263
              removeNodeFormat(editor, format, vars, child, format.exact ? child : null);
14264
            }
14265
          });
14266
        }
14267
        clearChildStyles(editor.dom, format, node);
14268
      });
14269
    };
14270
    const mergeWithParents = (editor, format, name, vars, node) => {
14271
      const parentNode = node.parentNode;
14272
      if (matchNode(editor, parentNode, name, vars)) {
14273
        if (removeNodeFormat(editor, format, vars, node)) {
14274
          return;
14275
        }
14276
      }
14277
      if (format.merge_with_parents && parentNode) {
14278
        editor.dom.getParent(parentNode, parent => {
14279
          if (matchNode(editor, parent, name, vars)) {
14280
            removeNodeFormat(editor, format, vars, node);
14281
            return true;
14282
          } else {
14283
            return false;
14284
          }
14285
        });
14286
      }
14287
    };
14288
 
14289
    const each$5 = Tools.each;
14290
    const canFormatBR = (editor, format, node, parentName) => {
14291
      if (canFormatEmptyLines(editor) && isInlineFormat(format) && node.parentNode) {
14292
        const validBRParentElements = getTextRootBlockElements(editor.schema);
14293
        const hasCaretNodeSibling = sibling(SugarElement.fromDom(node), sibling => isCaretNode(sibling.dom));
14294
        return hasNonNullableKey(validBRParentElements, parentName) && isEmpty$2(SugarElement.fromDom(node.parentNode), false) && !hasCaretNodeSibling;
14295
      } else {
14296
        return false;
14297
      }
14298
    };
14299
    const applyStyles = (dom, elm, format, vars) => {
14300
      each$5(format.styles, (value, name) => {
14301
        dom.setStyle(elm, name, replaceVars(value, vars));
14302
      });
14303
      if (format.styles) {
14304
        const styleVal = dom.getAttrib(elm, 'style');
14305
        if (styleVal) {
14306
          dom.setAttrib(elm, 'data-mce-style', styleVal);
14307
        }
14308
      }
14309
    };
14310
    const applyFormatAction = (ed, name, vars, node) => {
14311
      const formatList = ed.formatter.get(name);
14312
      const format = formatList[0];
14313
      const isCollapsed = !node && ed.selection.isCollapsed();
14314
      const dom = ed.dom;
14315
      const selection = ed.selection;
14316
      const setElementFormat = (elm, fmt = format) => {
14317
        if (isFunction(fmt.onformat)) {
14318
          fmt.onformat(elm, fmt, vars, node);
14319
        }
14320
        applyStyles(dom, elm, fmt, vars);
14321
        each$5(fmt.attributes, (value, name) => {
14322
          dom.setAttrib(elm, name, replaceVars(value, vars));
14323
        });
14324
        each$5(fmt.classes, value => {
14325
          const newValue = replaceVars(value, vars);
14326
          if (!dom.hasClass(elm, newValue)) {
14327
            dom.addClass(elm, newValue);
14328
          }
14329
        });
14330
      };
14331
      const applyNodeStyle = (formatList, node) => {
14332
        let found = false;
14333
        each$5(formatList, format => {
14334
          if (!isSelectorFormat(format)) {
14335
            return false;
14336
          }
14337
          if (dom.getContentEditable(node) === 'false' && !format.ceFalseOverride) {
14338
            return true;
14339
          }
14340
          if (isNonNullable(format.collapsed) && format.collapsed !== isCollapsed) {
14341
            return true;
14342
          }
14343
          if (dom.is(node, format.selector) && !isCaretNode(node)) {
14344
            setElementFormat(node, format);
14345
            found = true;
14346
            return false;
14347
          }
14348
          return true;
14349
        });
14350
        return found;
14351
      };
14352
      const createWrapElement = wrapName => {
14353
        if (isString(wrapName)) {
14354
          const wrapElm = dom.create(wrapName);
14355
          setElementFormat(wrapElm);
14356
          return wrapElm;
14357
        } else {
14358
          return null;
14359
        }
14360
      };
14361
      const applyRngStyle = (dom, rng, nodeSpecific) => {
14362
        const newWrappers = [];
14363
        let contentEditable = true;
14364
        const wrapName = format.inline || format.block;
14365
        const wrapElm = createWrapElement(wrapName);
14366
        const isMatchingWrappingBlock = node => isWrappingBlockFormat(format) && matchNode(ed, node, name, vars);
14367
        const canRenameBlock = (node, parentName, isEditableDescendant) => {
14368
          const isValidBlockFormatForNode = isNonWrappingBlockFormat(format) && isTextBlock$1(ed.schema, node) && isValid(ed, parentName, wrapName);
14369
          return isEditableDescendant && isValidBlockFormatForNode;
14370
        };
14371
        const canWrapNode = (node, parentName, isEditableDescendant, isWrappableNoneditableElm) => {
14372
          const nodeName = node.nodeName.toLowerCase();
14373
          const isValidWrapNode = isValid(ed, wrapName, nodeName) && isValid(ed, parentName, wrapName);
14374
          const isZwsp = !nodeSpecific && isText$a(node) && isZwsp$1(node.data);
14375
          const isCaret = isCaretNode(node);
14376
          const isCorrectFormatForNode = !isInlineFormat(format) || !dom.isBlock(node);
14377
          return (isEditableDescendant || isWrappableNoneditableElm) && isValidWrapNode && !isZwsp && !isCaret && isCorrectFormatForNode;
14378
        };
14379
        walk$3(dom, rng, nodes => {
14380
          let currentWrapElm;
14381
          const process = node => {
14382
            let hasContentEditableState = false;
14383
            let lastContentEditable = contentEditable;
14384
            let isWrappableNoneditableElm = false;
14385
            const parentNode = node.parentNode;
14386
            const parentName = parentNode.nodeName.toLowerCase();
14387
            const contentEditableValue = dom.getContentEditable(node);
14388
            if (isNonNullable(contentEditableValue)) {
14389
              lastContentEditable = contentEditable;
14390
              contentEditable = contentEditableValue === 'true';
14391
              hasContentEditableState = true;
14392
              isWrappableNoneditableElm = isWrappableNoneditable(ed, node);
14393
            }
14394
            const isEditableDescendant = contentEditable && !hasContentEditableState;
14395
            if (isBr$6(node) && !canFormatBR(ed, format, node, parentName)) {
14396
              currentWrapElm = null;
14397
              if (isBlockFormat(format)) {
14398
                dom.remove(node);
14399
              }
14400
              return;
14401
            }
14402
            if (isMatchingWrappingBlock(node)) {
14403
              currentWrapElm = null;
14404
              return;
14405
            }
14406
            if (canRenameBlock(node, parentName, isEditableDescendant)) {
14407
              const elm = dom.rename(node, wrapName);
14408
              setElementFormat(elm);
14409
              newWrappers.push(elm);
14410
              currentWrapElm = null;
14411
              return;
14412
            }
14413
            if (isSelectorFormat(format)) {
14414
              let found = applyNodeStyle(formatList, node);
14415
              if (!found && isNonNullable(parentNode) && shouldExpandToSelector(format)) {
14416
                found = applyNodeStyle(formatList, parentNode);
14417
              }
14418
              if (!isInlineFormat(format) || found) {
14419
                currentWrapElm = null;
14420
                return;
14421
              }
14422
            }
14423
            if (isNonNullable(wrapElm) && canWrapNode(node, parentName, isEditableDescendant, isWrappableNoneditableElm)) {
14424
              if (!currentWrapElm) {
14425
                currentWrapElm = dom.clone(wrapElm, false);
14426
                parentNode.insertBefore(currentWrapElm, node);
14427
                newWrappers.push(currentWrapElm);
14428
              }
14429
              if (isWrappableNoneditableElm && hasContentEditableState) {
14430
                contentEditable = lastContentEditable;
14431
              }
14432
              currentWrapElm.appendChild(node);
14433
            } else {
14434
              currentWrapElm = null;
14435
              each$e(from(node.childNodes), process);
14436
              if (hasContentEditableState) {
14437
                contentEditable = lastContentEditable;
14438
              }
14439
              currentWrapElm = null;
14440
            }
14441
          };
14442
          each$e(nodes, process);
14443
        });
14444
        if (format.links === true) {
14445
          each$e(newWrappers, node => {
14446
            const process = node => {
14447
              if (node.nodeName === 'A') {
14448
                setElementFormat(node, format);
14449
              }
14450
              each$e(from(node.childNodes), process);
14451
            };
14452
            process(node);
14453
          });
14454
        }
14455
        each$e(newWrappers, node => {
14456
          const getChildCount = node => {
14457
            let count = 0;
14458
            each$e(node.childNodes, node => {
14459
              if (!isEmptyTextNode$1(node) && !isBookmarkNode$1(node)) {
14460
                count++;
14461
              }
14462
            });
14463
            return count;
14464
          };
14465
          const mergeStyles = node => {
14466
            const childElement = find$2(node.childNodes, isElementNode$1).filter(child => dom.getContentEditable(child) !== 'false' && matchName(dom, child, format));
14467
            return childElement.map(child => {
14468
              const clone = dom.clone(child, false);
14469
              setElementFormat(clone);
14470
              dom.replace(clone, node, true);
14471
              dom.remove(child, true);
14472
              return clone;
14473
            }).getOr(node);
14474
          };
14475
          const childCount = getChildCount(node);
14476
          if ((newWrappers.length > 1 || !dom.isBlock(node)) && childCount === 0) {
14477
            dom.remove(node, true);
14478
            return;
14479
          }
14480
          if (isInlineFormat(format) || isBlockFormat(format) && format.wrapper) {
14481
            if (!format.exact && childCount === 1) {
14482
              node = mergeStyles(node);
14483
            }
14484
            mergeWithChildren(ed, formatList, vars, node);
14485
            mergeWithParents(ed, format, name, vars, node);
14486
            mergeBackgroundColorAndFontSize(dom, format, vars, node);
14487
            mergeTextDecorationsAndColor(dom, format, vars, node);
14488
            mergeSubSup(dom, format, vars, node);
14489
            mergeSiblings(ed, format, vars, node);
14490
          }
14491
        });
14492
      };
14493
      const targetNode = isNode(node) ? node : selection.getNode();
14494
      if (dom.getContentEditable(targetNode) === 'false' && !isWrappableNoneditable(ed, targetNode)) {
14495
        node = targetNode;
14496
        applyNodeStyle(formatList, node);
14497
        fireFormatApply(ed, name, node, vars);
14498
        return;
14499
      }
14500
      if (format) {
14501
        if (node) {
14502
          if (isNode(node)) {
14503
            if (!applyNodeStyle(formatList, node)) {
14504
              const rng = dom.createRng();
14505
              rng.setStartBefore(node);
14506
              rng.setEndAfter(node);
14507
              applyRngStyle(dom, expandRng(dom, rng, formatList), true);
14508
            }
14509
          } else {
14510
            applyRngStyle(dom, node, true);
14511
          }
14512
        } else {
14513
          if (!isCollapsed || !isInlineFormat(format) || getCellsFromEditor(ed).length) {
14514
            selection.setRng(normalize(selection.getRng()));
14515
            preserveSelection(ed, () => {
14516
              runOnRanges(ed, (selectionRng, fake) => {
14517
                const expandedRng = fake ? selectionRng : expandRng(dom, selectionRng, formatList);
14518
                applyRngStyle(dom, expandedRng, false);
14519
              });
14520
            }, always);
14521
            ed.nodeChanged();
14522
          } else {
14523
            applyCaretFormat(ed, name, vars);
14524
          }
14525
          getExpandedListItemFormat(ed.formatter, name).each(liFmt => {
14526
            each$e(getFullySelectedListItems(ed.selection), li => applyStyles(dom, li, liFmt, vars));
14527
          });
14528
        }
14529
        postProcess$1(name, ed);
14530
      }
14531
      fireFormatApply(ed, name, node, vars);
14532
    };
14533
    const applyFormat$1 = (editor, name, vars, node) => {
14534
      if (node || editor.selection.isEditable()) {
14535
        applyFormatAction(editor, name, vars, node);
14536
      }
14537
    };
14538
 
14539
    const hasVars = value => has$2(value, 'vars');
14540
    const setup$u = (registeredFormatListeners, editor) => {
14541
      registeredFormatListeners.set({});
14542
      editor.on('NodeChange', e => {
14543
        updateAndFireChangeCallbacks(editor, e.element, registeredFormatListeners.get());
14544
      });
14545
      editor.on('FormatApply FormatRemove', e => {
14546
        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));
14547
        updateAndFireChangeCallbacks(editor, element, registeredFormatListeners.get());
14548
      });
14549
    };
14550
    const fallbackElement = editor => editor.selection.getStart();
14551
    const matchingNode = (editor, parents, format, similar, vars) => {
14552
      const isMatchingNode = node => {
14553
        const matchingFormat = editor.formatter.matchNode(node, format, vars !== null && vars !== void 0 ? vars : {}, similar);
14554
        return !isUndefined(matchingFormat);
14555
      };
14556
      const isUnableToMatch = node => {
14557
        if (matchesUnInheritedFormatSelector(editor, node, format)) {
14558
          return true;
14559
        } else {
14560
          if (!similar) {
14561
            return isNonNullable(editor.formatter.matchNode(node, format, vars, true));
14562
          } else {
14563
            return false;
14564
          }
14565
        }
14566
      };
14567
      return findUntil$1(parents, isMatchingNode, isUnableToMatch);
14568
    };
14569
    const getParents = (editor, elm) => {
14570
      const element = elm !== null && elm !== void 0 ? elm : fallbackElement(editor);
14571
      return filter$5(getParents$2(editor.dom, element), node => isElement$6(node) && !isBogus$2(node));
14572
    };
14573
    const updateAndFireChangeCallbacks = (editor, elm, registeredCallbacks) => {
14574
      const parents = getParents(editor, elm);
14575
      each$d(registeredCallbacks, (data, format) => {
14576
        const runIfChanged = spec => {
14577
          const match = matchingNode(editor, parents, format, spec.similar, hasVars(spec) ? spec.vars : undefined);
14578
          const isSet = match.isSome();
14579
          if (spec.state.get() !== isSet) {
14580
            spec.state.set(isSet);
14581
            const node = match.getOr(elm);
14582
            if (hasVars(spec)) {
14583
              spec.callback(isSet, {
14584
                node,
14585
                format,
14586
                parents
14587
              });
14588
            } else {
14589
              each$e(spec.callbacks, callback => callback(isSet, {
14590
                node,
14591
                format,
14592
                parents
14593
              }));
14594
            }
14595
          }
14596
        };
14597
        each$e([
14598
          data.withSimilar,
14599
          data.withoutSimilar
14600
        ], runIfChanged);
14601
        each$e(data.withVars, runIfChanged);
14602
      });
14603
    };
14604
    const addListeners = (editor, registeredFormatListeners, formats, callback, similar, vars) => {
14605
      const formatChangeItems = registeredFormatListeners.get();
14606
      each$e(formats.split(','), format => {
14607
        const group = get$a(formatChangeItems, format).getOrThunk(() => {
14608
          const base = {
14609
            withSimilar: {
14610
              state: Cell(false),
14611
              similar: true,
14612
              callbacks: []
14613
            },
14614
            withoutSimilar: {
14615
              state: Cell(false),
14616
              similar: false,
14617
              callbacks: []
14618
            },
14619
            withVars: []
14620
          };
14621
          formatChangeItems[format] = base;
14622
          return base;
14623
        });
14624
        const getCurrent = () => {
14625
          const parents = getParents(editor);
14626
          return matchingNode(editor, parents, format, similar, vars).isSome();
14627
        };
14628
        if (isUndefined(vars)) {
14629
          const toAppendTo = similar ? group.withSimilar : group.withoutSimilar;
14630
          toAppendTo.callbacks.push(callback);
14631
          if (toAppendTo.callbacks.length === 1) {
14632
            toAppendTo.state.set(getCurrent());
14633
          }
14634
        } else {
14635
          group.withVars.push({
14636
            state: Cell(getCurrent()),
14637
            similar,
14638
            vars,
14639
            callback
14640
          });
14641
        }
14642
      });
14643
      registeredFormatListeners.set(formatChangeItems);
14644
    };
14645
    const removeListeners = (registeredFormatListeners, formats, callback) => {
14646
      const formatChangeItems = registeredFormatListeners.get();
14647
      each$e(formats.split(','), format => get$a(formatChangeItems, format).each(group => {
14648
        formatChangeItems[format] = {
14649
          withSimilar: {
14650
            ...group.withSimilar,
14651
            callbacks: filter$5(group.withSimilar.callbacks, cb => cb !== callback)
14652
          },
14653
          withoutSimilar: {
14654
            ...group.withoutSimilar,
14655
            callbacks: filter$5(group.withoutSimilar.callbacks, cb => cb !== callback)
14656
          },
14657
          withVars: filter$5(group.withVars, item => item.callback !== callback)
14658
        };
14659
      }));
14660
      registeredFormatListeners.set(formatChangeItems);
14661
    };
14662
    const formatChangedInternal = (editor, registeredFormatListeners, formats, callback, similar, vars) => {
14663
      addListeners(editor, registeredFormatListeners, formats, callback, similar, vars);
14664
      return { unbind: () => removeListeners(registeredFormatListeners, formats, callback) };
14665
    };
14666
 
14667
    const toggle = (editor, name, vars, node) => {
14668
      const fmt = editor.formatter.get(name);
14669
      if (fmt) {
14670
        if (match$2(editor, name, vars, node) && (!('toggle' in fmt[0]) || fmt[0].toggle)) {
14671
          removeFormat$1(editor, name, vars, node);
14672
        } else {
14673
          applyFormat$1(editor, name, vars, node);
14674
        }
14675
      }
14676
    };
14677
 
14678
    const explode$1 = Tools.explode;
14679
    const create$8 = () => {
14680
      const filters = {};
14681
      const addFilter = (name, callback) => {
14682
        each$e(explode$1(name), name => {
14683
          if (!has$2(filters, name)) {
14684
            filters[name] = {
14685
              name,
14686
              callbacks: []
14687
            };
14688
          }
14689
          filters[name].callbacks.push(callback);
14690
        });
14691
      };
14692
      const getFilters = () => values(filters);
14693
      const removeFilter = (name, callback) => {
14694
        each$e(explode$1(name), name => {
14695
          if (has$2(filters, name)) {
14696
            if (isNonNullable(callback)) {
14697
              const filter = filters[name];
14698
              const newCallbacks = filter$5(filter.callbacks, c => c !== callback);
14699
              if (newCallbacks.length > 0) {
14700
                filter.callbacks = newCallbacks;
14701
              } else {
14702
                delete filters[name];
14703
              }
14704
            } else {
14705
              delete filters[name];
14706
            }
14707
          }
14708
        });
14709
      };
14710
      return {
14711
        addFilter,
14712
        getFilters,
14713
        removeFilter
14714
      };
14715
    };
14716
 
14717
    const removeAttrs = (node, names) => {
14718
      each$e(names, name => {
14719
        node.attr(name, null);
14720
      });
14721
    };
14722
    const addFontToSpansFilter = (domParser, styles, fontSizes) => {
14723
      domParser.addNodeFilter('font', nodes => {
14724
        each$e(nodes, node => {
14725
          const props = styles.parse(node.attr('style'));
14726
          const color = node.attr('color');
14727
          const face = node.attr('face');
14728
          const size = node.attr('size');
14729
          if (color) {
14730
            props.color = color;
14731
          }
14732
          if (face) {
14733
            props['font-family'] = face;
14734
          }
14735
          if (size) {
14736
            toInt(size).each(num => {
14737
              props['font-size'] = fontSizes[num - 1];
14738
            });
14739
          }
14740
          node.name = 'span';
14741
          node.attr('style', styles.serialize(props));
14742
          removeAttrs(node, [
14743
            'color',
14744
            'face',
14745
            'size'
14746
          ]);
14747
        });
14748
      });
14749
    };
14750
    const addStrikeFilter = (domParser, schema, styles) => {
14751
      domParser.addNodeFilter('strike', nodes => {
14752
        const convertToSTag = schema.type !== 'html4';
14753
        each$e(nodes, node => {
14754
          if (convertToSTag) {
14755
            node.name = 's';
14756
          } else {
14757
            const props = styles.parse(node.attr('style'));
14758
            props['text-decoration'] = 'line-through';
14759
            node.name = 'span';
14760
            node.attr('style', styles.serialize(props));
14761
          }
14762
        });
14763
      });
14764
    };
14765
    const addFilters = (domParser, settings, schema) => {
14766
      var _a;
14767
      const styles = Styles();
14768
      if (settings.convert_fonts_to_spans) {
14769
        addFontToSpansFilter(domParser, styles, Tools.explode((_a = settings.font_size_legacy_values) !== null && _a !== void 0 ? _a : ''));
14770
      }
14771
      addStrikeFilter(domParser, schema, styles);
14772
    };
14773
    const register$5 = (domParser, settings, schema) => {
14774
      if (settings.inline_styles) {
14775
        addFilters(domParser, settings, schema);
14776
      }
14777
    };
14778
 
14779
    const addNodeFilter = (settings, htmlParser, schema) => {
14780
      htmlParser.addNodeFilter('br', (nodes, _, args) => {
14781
        const blockElements = Tools.extend({}, schema.getBlockElements());
14782
        const nonEmptyElements = schema.getNonEmptyElements();
14783
        const whitespaceElements = schema.getWhitespaceElements();
14784
        blockElements.body = 1;
14785
        const isBlock = node => node.name in blockElements || isTransparentAstBlock(schema, node);
14786
        for (let i = 0, l = nodes.length; i < l; i++) {
14787
          let node = nodes[i];
14788
          let parent = node.parent;
14789
          if (parent && isBlock(parent) && node === parent.lastChild) {
14790
            let prev = node.prev;
14791
            while (prev) {
14792
              const prevName = prev.name;
14793
              if (prevName !== 'span' || prev.attr('data-mce-type') !== 'bookmark') {
14794
                if (prevName === 'br') {
14795
                  node = null;
14796
                }
14797
                break;
14798
              }
14799
              prev = prev.prev;
14800
            }
14801
            if (node) {
14802
              node.remove();
14803
              if (isEmpty(schema, nonEmptyElements, whitespaceElements, parent)) {
14804
                const elementRule = schema.getElementRule(parent.name);
14805
                if (elementRule) {
14806
                  if (elementRule.removeEmpty) {
14807
                    parent.remove();
14808
                  } else if (elementRule.paddEmpty) {
14809
                    paddEmptyNode(settings, args, isBlock, parent);
14810
                  }
14811
                }
14812
              }
14813
            }
14814
          } else {
14815
            let lastParent = node;
14816
            while (parent && parent.firstChild === lastParent && parent.lastChild === lastParent) {
14817
              lastParent = parent;
14818
              if (blockElements[parent.name]) {
14819
                break;
14820
              }
14821
              parent = parent.parent;
14822
            }
14823
            if (lastParent === parent) {
14824
              const textNode = new AstNode('#text', 3);
14825
              textNode.value = nbsp;
14826
              node.replace(textNode);
14827
            }
14828
          }
14829
        }
14830
      });
14831
    };
14832
 
14833
    const blobUriToBlob = url => fetch(url).then(res => res.ok ? res.blob() : Promise.reject()).catch(() => Promise.reject({
14834
      message: `Cannot convert ${ url } to Blob. Resource might not exist or is inaccessible.`,
14835
      uriType: 'blob'
14836
    }));
14837
    const extractBase64Data = data => {
14838
      const matches = /([a-z0-9+\/=\s]+)/i.exec(data);
14839
      return matches ? matches[1] : '';
14840
    };
14841
    const parseDataUri = uri => {
14842
      const [type, ...rest] = uri.split(',');
14843
      const data = rest.join(',');
14844
      const matches = /data:([^/]+\/[^;]+)(;.+)?/.exec(type);
14845
      if (matches) {
14846
        const base64Encoded = matches[2] === ';base64';
14847
        const extractedData = base64Encoded ? extractBase64Data(data) : decodeURIComponent(data);
14848
        return Optional.some({
14849
          type: matches[1],
14850
          data: extractedData,
14851
          base64Encoded
14852
        });
14853
      } else {
14854
        return Optional.none();
14855
      }
14856
    };
14857
    const buildBlob = (type, data, base64Encoded = true) => {
14858
      let str = data;
14859
      if (base64Encoded) {
14860
        try {
14861
          str = atob(data);
14862
        } catch (e) {
14863
          return Optional.none();
14864
        }
14865
      }
14866
      const arr = new Uint8Array(str.length);
14867
      for (let i = 0; i < arr.length; i++) {
14868
        arr[i] = str.charCodeAt(i);
14869
      }
14870
      return Optional.some(new Blob([arr], { type }));
14871
    };
14872
    const dataUriToBlob = uri => {
14873
      return new Promise((resolve, reject) => {
14874
        parseDataUri(uri).bind(({type, data, base64Encoded}) => buildBlob(type, data, base64Encoded)).fold(() => reject('Invalid data URI'), resolve);
14875
      });
14876
    };
14877
    const uriToBlob = url => {
14878
      if (startsWith(url, 'blob:')) {
14879
        return blobUriToBlob(url);
14880
      } else if (startsWith(url, 'data:')) {
14881
        return dataUriToBlob(url);
14882
      } else {
14883
        return Promise.reject('Unknown URI format');
14884
      }
14885
    };
14886
    const blobToDataUri = blob => {
14887
      return new Promise((resolve, reject) => {
14888
        const reader = new FileReader();
14889
        reader.onloadend = () => {
14890
          resolve(reader.result);
14891
        };
14892
        reader.onerror = () => {
14893
          var _a;
14894
          reject((_a = reader.error) === null || _a === void 0 ? void 0 : _a.message);
14895
        };
14896
        reader.readAsDataURL(blob);
14897
      });
14898
    };
14899
 
14900
    let count$1 = 0;
14901
    const uniqueId$1 = prefix => {
14902
      return (prefix || 'blobid') + count$1++;
14903
    };
14904
    const processDataUri = (dataUri, base64Only, generateBlobInfo) => {
14905
      return parseDataUri(dataUri).bind(({data, type, base64Encoded}) => {
14906
        if (base64Only && !base64Encoded) {
14907
          return Optional.none();
14908
        } else {
14909
          const base64 = base64Encoded ? data : btoa(data);
14910
          return generateBlobInfo(base64, type);
14911
        }
14912
      });
14913
    };
14914
    const createBlobInfo$1 = (blobCache, blob, base64) => {
14915
      const blobInfo = blobCache.create(uniqueId$1(), blob, base64);
14916
      blobCache.add(blobInfo);
14917
      return blobInfo;
14918
    };
14919
    const dataUriToBlobInfo = (blobCache, dataUri, base64Only = false) => {
14920
      return processDataUri(dataUri, base64Only, (base64, type) => Optional.from(blobCache.getByData(base64, type)).orThunk(() => buildBlob(type, base64).map(blob => createBlobInfo$1(blobCache, blob, base64))));
14921
    };
14922
    const imageToBlobInfo = (blobCache, imageSrc) => {
14923
      const invalidDataUri = () => Promise.reject('Invalid data URI');
14924
      if (startsWith(imageSrc, 'blob:')) {
14925
        const blobInfo = blobCache.getByUri(imageSrc);
14926
        if (isNonNullable(blobInfo)) {
14927
          return Promise.resolve(blobInfo);
14928
        } else {
14929
          return uriToBlob(imageSrc).then(blob => {
14930
            return blobToDataUri(blob).then(dataUri => {
14931
              return processDataUri(dataUri, false, base64 => {
14932
                return Optional.some(createBlobInfo$1(blobCache, blob, base64));
14933
              }).getOrThunk(invalidDataUri);
14934
            });
14935
          });
14936
        }
14937
      } else if (startsWith(imageSrc, 'data:')) {
14938
        return dataUriToBlobInfo(blobCache, imageSrc).fold(invalidDataUri, blobInfo => Promise.resolve(blobInfo));
14939
      } else {
14940
        return Promise.reject('Unknown image data format');
14941
      }
14942
    };
14943
 
14944
    const isBogusImage = img => isNonNullable(img.attr('data-mce-bogus'));
14945
    const isInternalImageSource = img => img.attr('src') === Env.transparentSrc || isNonNullable(img.attr('data-mce-placeholder'));
14946
    const registerBase64ImageFilter = (parser, settings) => {
14947
      const {blob_cache: blobCache} = settings;
14948
      if (blobCache) {
14949
        const processImage = img => {
14950
          const inputSrc = img.attr('src');
14951
          if (isInternalImageSource(img) || isBogusImage(img) || isNullable(inputSrc)) {
14952
            return;
14953
          }
14954
          dataUriToBlobInfo(blobCache, inputSrc, true).each(blobInfo => {
14955
            img.attr('src', blobInfo.blobUri());
14956
          });
14957
        };
14958
        parser.addAttributeFilter('src', nodes => each$e(nodes, processImage));
14959
      }
14960
    };
14961
    const isMimeType = (mime, type) => startsWith(mime, `${ type }/`);
14962
    const createSafeEmbed = (mime, src, width, height, sandboxIframes) => {
14963
      let name;
14964
      if (isUndefined(mime)) {
14965
        name = 'iframe';
14966
      } else if (isMimeType(mime, 'image')) {
14967
        name = 'img';
14968
      } else if (isMimeType(mime, 'video')) {
14969
        name = 'video';
14970
      } else if (isMimeType(mime, 'audio')) {
14971
        name = 'audio';
14972
      } else {
14973
        name = 'iframe';
14974
      }
14975
      const embed = new AstNode(name, 1);
14976
      embed.attr(name === 'audio' ? { src } : {
14977
        src,
14978
        width,
14979
        height
14980
      });
14981
      if (name === 'audio' || name === 'video') {
14982
        embed.attr('controls', '');
14983
      }
14984
      if (name === 'iframe' && sandboxIframes) {
14985
        embed.attr('sandbox', '');
14986
      }
14987
      return embed;
14988
    };
14989
    const register$4 = (parser, settings) => {
14990
      const schema = parser.schema;
14991
      if (settings.remove_trailing_brs) {
14992
        addNodeFilter(settings, parser, schema);
14993
      }
14994
      parser.addAttributeFilter('href', nodes => {
14995
        let i = nodes.length;
14996
        const appendRel = rel => {
14997
          const parts = rel.split(' ').filter(p => p.length > 0);
14998
          return parts.concat(['noopener']).sort().join(' ');
14999
        };
15000
        const addNoOpener = rel => {
15001
          const newRel = rel ? Tools.trim(rel) : '';
15002
          if (!/\b(noopener)\b/g.test(newRel)) {
15003
            return appendRel(newRel);
15004
          } else {
15005
            return newRel;
15006
          }
15007
        };
15008
        if (!settings.allow_unsafe_link_target) {
15009
          while (i--) {
15010
            const node = nodes[i];
15011
            if (node.name === 'a' && node.attr('target') === '_blank') {
15012
              node.attr('rel', addNoOpener(node.attr('rel')));
15013
            }
15014
          }
15015
        }
15016
      });
15017
      if (!settings.allow_html_in_named_anchor) {
15018
        parser.addAttributeFilter('id,name', nodes => {
15019
          let i = nodes.length, sibling, prevSibling, parent, node;
15020
          while (i--) {
15021
            node = nodes[i];
15022
            if (node.name === 'a' && node.firstChild && !node.attr('href')) {
15023
              parent = node.parent;
15024
              sibling = node.lastChild;
15025
              while (sibling && parent) {
15026
                prevSibling = sibling.prev;
15027
                parent.insert(sibling, node);
15028
                sibling = prevSibling;
15029
              }
15030
            }
15031
          }
15032
        });
15033
      }
15034
      if (settings.fix_list_elements) {
15035
        parser.addNodeFilter('ul,ol', nodes => {
15036
          let i = nodes.length, node, parentNode;
15037
          while (i--) {
15038
            node = nodes[i];
15039
            parentNode = node.parent;
15040
            if (parentNode && (parentNode.name === 'ul' || parentNode.name === 'ol')) {
15041
              if (node.prev && node.prev.name === 'li') {
15042
                node.prev.append(node);
15043
              } else {
15044
                const li = new AstNode('li', 1);
15045
                li.attr('style', 'list-style-type: none');
15046
                node.wrap(li);
15047
              }
15048
            }
15049
          }
15050
        });
15051
      }
15052
      const validClasses = schema.getValidClasses();
15053
      if (settings.validate && validClasses) {
15054
        parser.addAttributeFilter('class', nodes => {
15055
          var _a;
15056
          let i = nodes.length;
15057
          while (i--) {
15058
            const node = nodes[i];
15059
            const clazz = (_a = node.attr('class')) !== null && _a !== void 0 ? _a : '';
15060
            const classList = Tools.explode(clazz, ' ');
15061
            let classValue = '';
15062
            for (let ci = 0; ci < classList.length; ci++) {
15063
              const className = classList[ci];
15064
              let valid = false;
15065
              let validClassesMap = validClasses['*'];
15066
              if (validClassesMap && validClassesMap[className]) {
15067
                valid = true;
15068
              }
15069
              validClassesMap = validClasses[node.name];
15070
              if (!valid && validClassesMap && validClassesMap[className]) {
15071
                valid = true;
15072
              }
15073
              if (valid) {
15074
                if (classValue) {
15075
                  classValue += ' ';
15076
                }
15077
                classValue += className;
15078
              }
15079
            }
15080
            if (!classValue.length) {
15081
              classValue = null;
15082
            }
15083
            node.attr('class', classValue);
15084
          }
15085
        });
15086
      }
15087
      registerBase64ImageFilter(parser, settings);
15088
      if (settings.convert_unsafe_embeds) {
15089
        parser.addNodeFilter('object,embed', nodes => each$e(nodes, node => {
15090
          node.replace(createSafeEmbed(node.attr('type'), node.name === 'object' ? node.attr('data') : node.attr('src'), node.attr('width'), node.attr('height'), settings.sandbox_iframes));
15091
        }));
15092
      }
15093
      if (settings.sandbox_iframes) {
15094
        parser.addNodeFilter('iframe', nodes => each$e(nodes, node => node.attr('sandbox', '')));
15095
      }
15096
    };
15097
 
15098
    const {entries, setPrototypeOf, isFrozen, getPrototypeOf, getOwnPropertyDescriptor} = Object;
15099
    let {freeze, seal, create: create$7} = Object;
15100
    let {apply, construct} = typeof Reflect !== 'undefined' && Reflect;
15101
    if (!apply) {
15102
      apply = function apply(fun, thisValue, args) {
15103
        return fun.apply(thisValue, args);
15104
      };
15105
    }
15106
    if (!freeze) {
15107
      freeze = function freeze(x) {
15108
        return x;
15109
      };
15110
    }
15111
    if (!seal) {
15112
      seal = function seal(x) {
15113
        return x;
15114
      };
15115
    }
15116
    if (!construct) {
15117
      construct = function construct(Func, args) {
15118
        return new Func(...args);
15119
      };
15120
    }
15121
    const arrayForEach = unapply(Array.prototype.forEach);
15122
    const arrayPop = unapply(Array.prototype.pop);
15123
    const arrayPush = unapply(Array.prototype.push);
15124
    const stringToLowerCase = unapply(String.prototype.toLowerCase);
15125
    const stringToString = unapply(String.prototype.toString);
15126
    const stringMatch = unapply(String.prototype.match);
15127
    const stringReplace = unapply(String.prototype.replace);
15128
    const stringIndexOf = unapply(String.prototype.indexOf);
15129
    const stringTrim = unapply(String.prototype.trim);
15130
    const regExpTest = unapply(RegExp.prototype.test);
15131
    const typeErrorCreate = unconstruct(TypeError);
15132
    function unapply(func) {
15133
      return function (thisArg) {
15134
        for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
15135
          args[_key - 1] = arguments[_key];
15136
        }
15137
        return apply(func, thisArg, args);
15138
      };
15139
    }
15140
    function unconstruct(func) {
15141
      return function () {
15142
        for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
15143
          args[_key2] = arguments[_key2];
15144
        }
15145
        return construct(func, args);
15146
      };
15147
    }
15148
    function addToSet(set, array, transformCaseFunc) {
15149
      var _transformCaseFunc;
15150
      transformCaseFunc = (_transformCaseFunc = transformCaseFunc) !== null && _transformCaseFunc !== void 0 ? _transformCaseFunc : stringToLowerCase;
15151
      if (setPrototypeOf) {
15152
        setPrototypeOf(set, null);
15153
      }
15154
      let l = array.length;
15155
      while (l--) {
15156
        let element = array[l];
15157
        if (typeof element === 'string') {
15158
          const lcElement = transformCaseFunc(element);
15159
          if (lcElement !== element) {
15160
            if (!isFrozen(array)) {
15161
              array[l] = lcElement;
15162
            }
15163
            element = lcElement;
15164
          }
15165
        }
15166
        set[element] = true;
15167
      }
15168
      return set;
15169
    }
15170
    function clone(object) {
15171
      const newObject = create$7(null);
15172
      for (const [property, value] of entries(object)) {
15173
        newObject[property] = value;
15174
      }
15175
      return newObject;
15176
    }
15177
    function lookupGetter(object, prop) {
15178
      while (object !== null) {
15179
        const desc = getOwnPropertyDescriptor(object, prop);
15180
        if (desc) {
15181
          if (desc.get) {
15182
            return unapply(desc.get);
15183
          }
15184
          if (typeof desc.value === 'function') {
15185
            return unapply(desc.value);
15186
          }
15187
        }
15188
        object = getPrototypeOf(object);
15189
      }
15190
      function fallbackValue(element) {
15191
        console.warn('fallback value for', element);
15192
        return null;
15193
      }
15194
      return fallbackValue;
15195
    }
15196
    const html$1 = freeze([
15197
      'a',
15198
      'abbr',
15199
      'acronym',
15200
      'address',
15201
      'area',
15202
      'article',
15203
      'aside',
15204
      'audio',
15205
      'b',
15206
      'bdi',
15207
      'bdo',
15208
      'big',
15209
      'blink',
15210
      'blockquote',
15211
      'body',
15212
      'br',
15213
      'button',
15214
      'canvas',
15215
      'caption',
15216
      'center',
15217
      'cite',
15218
      'code',
15219
      'col',
15220
      'colgroup',
15221
      'content',
15222
      'data',
15223
      'datalist',
15224
      'dd',
15225
      'decorator',
15226
      'del',
15227
      'details',
15228
      'dfn',
15229
      'dialog',
15230
      'dir',
15231
      'div',
15232
      'dl',
15233
      'dt',
15234
      'element',
15235
      'em',
15236
      'fieldset',
15237
      'figcaption',
15238
      'figure',
15239
      'font',
15240
      'footer',
15241
      'form',
15242
      'h1',
15243
      'h2',
15244
      'h3',
15245
      'h4',
15246
      'h5',
15247
      'h6',
15248
      'head',
15249
      'header',
15250
      'hgroup',
15251
      'hr',
15252
      'html',
15253
      'i',
15254
      'img',
15255
      'input',
15256
      'ins',
15257
      'kbd',
15258
      'label',
15259
      'legend',
15260
      'li',
15261
      'main',
15262
      'map',
15263
      'mark',
15264
      'marquee',
15265
      'menu',
15266
      'menuitem',
15267
      'meter',
15268
      'nav',
15269
      'nobr',
15270
      'ol',
15271
      'optgroup',
15272
      'option',
15273
      'output',
15274
      'p',
15275
      'picture',
15276
      'pre',
15277
      'progress',
15278
      'q',
15279
      'rp',
15280
      'rt',
15281
      'ruby',
15282
      's',
15283
      'samp',
15284
      'section',
15285
      'select',
15286
      'shadow',
15287
      'small',
15288
      'source',
15289
      'spacer',
15290
      'span',
15291
      'strike',
15292
      'strong',
15293
      'style',
15294
      'sub',
15295
      'summary',
15296
      'sup',
15297
      'table',
15298
      'tbody',
15299
      'td',
15300
      'template',
15301
      'textarea',
15302
      'tfoot',
15303
      'th',
15304
      'thead',
15305
      'time',
15306
      'tr',
15307
      'track',
15308
      'tt',
15309
      'u',
15310
      'ul',
15311
      'var',
15312
      'video',
15313
      'wbr'
15314
    ]);
15315
    const svg$1 = freeze([
15316
      'svg',
15317
      'a',
15318
      'altglyph',
15319
      'altglyphdef',
15320
      'altglyphitem',
15321
      'animatecolor',
15322
      'animatemotion',
15323
      'animatetransform',
15324
      'circle',
15325
      'clippath',
15326
      'defs',
15327
      'desc',
15328
      'ellipse',
15329
      'filter',
15330
      'font',
15331
      'g',
15332
      'glyph',
15333
      'glyphref',
15334
      'hkern',
15335
      'image',
15336
      'line',
15337
      'lineargradient',
15338
      'marker',
15339
      'mask',
15340
      'metadata',
15341
      'mpath',
15342
      'path',
15343
      'pattern',
15344
      'polygon',
15345
      'polyline',
15346
      'radialgradient',
15347
      'rect',
15348
      'stop',
15349
      'style',
15350
      'switch',
15351
      'symbol',
15352
      'text',
15353
      'textpath',
15354
      'title',
15355
      'tref',
15356
      'tspan',
15357
      'view',
15358
      'vkern'
15359
    ]);
15360
    const svgFilters = freeze([
15361
      'feBlend',
15362
      'feColorMatrix',
15363
      'feComponentTransfer',
15364
      'feComposite',
15365
      'feConvolveMatrix',
15366
      'feDiffuseLighting',
15367
      'feDisplacementMap',
15368
      'feDistantLight',
15369
      'feDropShadow',
15370
      'feFlood',
15371
      'feFuncA',
15372
      'feFuncB',
15373
      'feFuncG',
15374
      'feFuncR',
15375
      'feGaussianBlur',
15376
      'feImage',
15377
      'feMerge',
15378
      'feMergeNode',
15379
      'feMorphology',
15380
      'feOffset',
15381
      'fePointLight',
15382
      'feSpecularLighting',
15383
      'feSpotLight',
15384
      'feTile',
15385
      'feTurbulence'
15386
    ]);
15387
    const svgDisallowed = freeze([
15388
      'animate',
15389
      'color-profile',
15390
      'cursor',
15391
      'discard',
15392
      'font-face',
15393
      'font-face-format',
15394
      'font-face-name',
15395
      'font-face-src',
15396
      'font-face-uri',
15397
      'foreignobject',
15398
      'hatch',
15399
      'hatchpath',
15400
      'mesh',
15401
      'meshgradient',
15402
      'meshpatch',
15403
      'meshrow',
15404
      'missing-glyph',
15405
      'script',
15406
      'set',
15407
      'solidcolor',
15408
      'unknown',
15409
      'use'
15410
    ]);
15411
    const mathMl$1 = freeze([
15412
      'math',
15413
      'menclose',
15414
      'merror',
15415
      'mfenced',
15416
      'mfrac',
15417
      'mglyph',
15418
      'mi',
15419
      'mlabeledtr',
15420
      'mmultiscripts',
15421
      'mn',
15422
      'mo',
15423
      'mover',
15424
      'mpadded',
15425
      'mphantom',
15426
      'mroot',
15427
      'mrow',
15428
      'ms',
15429
      'mspace',
15430
      'msqrt',
15431
      'mstyle',
15432
      'msub',
15433
      'msup',
15434
      'msubsup',
15435
      'mtable',
15436
      'mtd',
15437
      'mtext',
15438
      'mtr',
15439
      'munder',
15440
      'munderover',
15441
      'mprescripts'
15442
    ]);
15443
    const mathMlDisallowed = freeze([
15444
      'maction',
15445
      'maligngroup',
15446
      'malignmark',
15447
      'mlongdiv',
15448
      'mscarries',
15449
      'mscarry',
15450
      'msgroup',
15451
      'mstack',
15452
      'msline',
15453
      'msrow',
15454
      'semantics',
15455
      'annotation',
15456
      'annotation-xml',
15457
      'mprescripts',
15458
      'none'
15459
    ]);
15460
    const text = freeze(['#text']);
15461
    const html = freeze([
15462
      'accept',
15463
      'action',
15464
      'align',
15465
      'alt',
15466
      'autocapitalize',
15467
      'autocomplete',
15468
      'autopictureinpicture',
15469
      'autoplay',
15470
      'background',
15471
      'bgcolor',
15472
      'border',
15473
      'capture',
15474
      'cellpadding',
15475
      'cellspacing',
15476
      'checked',
15477
      'cite',
15478
      'class',
15479
      'clear',
15480
      'color',
15481
      'cols',
15482
      'colspan',
15483
      'controls',
15484
      'controlslist',
15485
      'coords',
15486
      'crossorigin',
15487
      'datetime',
15488
      'decoding',
15489
      'default',
15490
      'dir',
15491
      'disabled',
15492
      'disablepictureinpicture',
15493
      'disableremoteplayback',
15494
      'download',
15495
      'draggable',
15496
      'enctype',
15497
      'enterkeyhint',
15498
      'face',
15499
      'for',
15500
      'headers',
15501
      'height',
15502
      'hidden',
15503
      'high',
15504
      'href',
15505
      'hreflang',
15506
      'id',
15507
      'inputmode',
15508
      'integrity',
15509
      'ismap',
15510
      'kind',
15511
      'label',
15512
      'lang',
15513
      'list',
15514
      'loading',
15515
      'loop',
15516
      'low',
15517
      'max',
15518
      'maxlength',
15519
      'media',
15520
      'method',
15521
      'min',
15522
      'minlength',
15523
      'multiple',
15524
      'muted',
15525
      'name',
15526
      'nonce',
15527
      'noshade',
15528
      'novalidate',
15529
      'nowrap',
15530
      'open',
15531
      'optimum',
15532
      'pattern',
15533
      'placeholder',
15534
      'playsinline',
15535
      'poster',
15536
      'preload',
15537
      'pubdate',
15538
      'radiogroup',
15539
      'readonly',
15540
      'rel',
15541
      'required',
15542
      'rev',
15543
      'reversed',
15544
      'role',
15545
      'rows',
15546
      'rowspan',
15547
      'spellcheck',
15548
      'scope',
15549
      'selected',
15550
      'shape',
15551
      'size',
15552
      'sizes',
15553
      'span',
15554
      'srclang',
15555
      'start',
15556
      'src',
15557
      'srcset',
15558
      'step',
15559
      'style',
15560
      'summary',
15561
      'tabindex',
15562
      'title',
15563
      'translate',
15564
      'type',
15565
      'usemap',
15566
      'valign',
15567
      'value',
15568
      'width',
15569
      'xmlns',
15570
      'slot'
15571
    ]);
15572
    const svg = freeze([
15573
      'accent-height',
15574
      'accumulate',
15575
      'additive',
15576
      'alignment-baseline',
15577
      'ascent',
15578
      'attributename',
15579
      'attributetype',
15580
      'azimuth',
15581
      'basefrequency',
15582
      'baseline-shift',
15583
      'begin',
15584
      'bias',
15585
      'by',
15586
      'class',
15587
      'clip',
15588
      'clippathunits',
15589
      'clip-path',
15590
      'clip-rule',
15591
      'color',
15592
      'color-interpolation',
15593
      'color-interpolation-filters',
15594
      'color-profile',
15595
      'color-rendering',
15596
      'cx',
15597
      'cy',
15598
      'd',
15599
      'dx',
15600
      'dy',
15601
      'diffuseconstant',
15602
      'direction',
15603
      'display',
15604
      'divisor',
15605
      'dur',
15606
      'edgemode',
15607
      'elevation',
15608
      'end',
15609
      'fill',
15610
      'fill-opacity',
15611
      'fill-rule',
15612
      'filter',
15613
      'filterunits',
15614
      'flood-color',
15615
      'flood-opacity',
15616
      'font-family',
15617
      'font-size',
15618
      'font-size-adjust',
15619
      'font-stretch',
15620
      'font-style',
15621
      'font-variant',
15622
      'font-weight',
15623
      'fx',
15624
      'fy',
15625
      'g1',
15626
      'g2',
15627
      'glyph-name',
15628
      'glyphref',
15629
      'gradientunits',
15630
      'gradienttransform',
15631
      'height',
15632
      'href',
15633
      'id',
15634
      'image-rendering',
15635
      'in',
15636
      'in2',
15637
      'k',
15638
      'k1',
15639
      'k2',
15640
      'k3',
15641
      'k4',
15642
      'kerning',
15643
      'keypoints',
15644
      'keysplines',
15645
      'keytimes',
15646
      'lang',
15647
      'lengthadjust',
15648
      'letter-spacing',
15649
      'kernelmatrix',
15650
      'kernelunitlength',
15651
      'lighting-color',
15652
      'local',
15653
      'marker-end',
15654
      'marker-mid',
15655
      'marker-start',
15656
      'markerheight',
15657
      'markerunits',
15658
      'markerwidth',
15659
      'maskcontentunits',
15660
      'maskunits',
15661
      'max',
15662
      'mask',
15663
      'media',
15664
      'method',
15665
      'mode',
15666
      'min',
15667
      'name',
15668
      'numoctaves',
15669
      'offset',
15670
      'operator',
15671
      'opacity',
15672
      'order',
15673
      'orient',
15674
      'orientation',
15675
      'origin',
15676
      'overflow',
15677
      'paint-order',
15678
      'path',
15679
      'pathlength',
15680
      'patterncontentunits',
15681
      'patterntransform',
15682
      'patternunits',
15683
      'points',
15684
      'preservealpha',
15685
      'preserveaspectratio',
15686
      'primitiveunits',
15687
      'r',
15688
      'rx',
15689
      'ry',
15690
      'radius',
15691
      'refx',
15692
      'refy',
15693
      'repeatcount',
15694
      'repeatdur',
15695
      'restart',
15696
      'result',
15697
      'rotate',
15698
      'scale',
15699
      'seed',
15700
      'shape-rendering',
15701
      'specularconstant',
15702
      'specularexponent',
15703
      'spreadmethod',
15704
      'startoffset',
15705
      'stddeviation',
15706
      'stitchtiles',
15707
      'stop-color',
15708
      'stop-opacity',
15709
      'stroke-dasharray',
15710
      'stroke-dashoffset',
15711
      'stroke-linecap',
15712
      'stroke-linejoin',
15713
      'stroke-miterlimit',
15714
      'stroke-opacity',
15715
      'stroke',
15716
      'stroke-width',
15717
      'style',
15718
      'surfacescale',
15719
      'systemlanguage',
15720
      'tabindex',
15721
      'targetx',
15722
      'targety',
15723
      'transform',
15724
      'transform-origin',
15725
      'text-anchor',
15726
      'text-decoration',
15727
      'text-rendering',
15728
      'textlength',
15729
      'type',
15730
      'u1',
15731
      'u2',
15732
      'unicode',
15733
      'values',
15734
      'viewbox',
15735
      'visibility',
15736
      'version',
15737
      'vert-adv-y',
15738
      'vert-origin-x',
15739
      'vert-origin-y',
15740
      'width',
15741
      'word-spacing',
15742
      'wrap',
15743
      'writing-mode',
15744
      'xchannelselector',
15745
      'ychannelselector',
15746
      'x',
15747
      'x1',
15748
      'x2',
15749
      'xmlns',
15750
      'y',
15751
      'y1',
15752
      'y2',
15753
      'z',
15754
      'zoomandpan'
15755
    ]);
15756
    const mathMl = freeze([
15757
      'accent',
15758
      'accentunder',
15759
      'align',
15760
      'bevelled',
15761
      'close',
15762
      'columnsalign',
15763
      'columnlines',
15764
      'columnspan',
15765
      'denomalign',
15766
      'depth',
15767
      'dir',
15768
      'display',
15769
      'displaystyle',
15770
      'encoding',
15771
      'fence',
15772
      'frame',
15773
      'height',
15774
      'href',
15775
      'id',
15776
      'largeop',
15777
      'length',
15778
      'linethickness',
15779
      'lspace',
15780
      'lquote',
15781
      'mathbackground',
15782
      'mathcolor',
15783
      'mathsize',
15784
      'mathvariant',
15785
      'maxsize',
15786
      'minsize',
15787
      'movablelimits',
15788
      'notation',
15789
      'numalign',
15790
      'open',
15791
      'rowalign',
15792
      'rowlines',
15793
      'rowspacing',
15794
      'rowspan',
15795
      'rspace',
15796
      'rquote',
15797
      'scriptlevel',
15798
      'scriptminsize',
15799
      'scriptsizemultiplier',
15800
      'selection',
15801
      'separator',
15802
      'separators',
15803
      'stretchy',
15804
      'subscriptshift',
15805
      'supscriptshift',
15806
      'symmetric',
15807
      'voffset',
15808
      'width',
15809
      'xmlns'
15810
    ]);
15811
    const xml = freeze([
15812
      'xlink:href',
15813
      'xml:id',
15814
      'xlink:title',
15815
      'xml:space',
15816
      'xmlns:xlink'
15817
    ]);
15818
    const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
15819
    const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
15820
    const TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
15821
    const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/);
15822
    const ARIA_ATTR = seal(/^aria-[\-\w]+$/);
15823
    const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i);
15824
    const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
15825
    const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g);
15826
    const DOCTYPE_NAME = seal(/^html$/i);
15827
    var EXPRESSIONS = Object.freeze({
15828
      __proto__: null,
15829
      MUSTACHE_EXPR: MUSTACHE_EXPR,
15830
      ERB_EXPR: ERB_EXPR,
15831
      TMPLIT_EXPR: TMPLIT_EXPR,
15832
      DATA_ATTR: DATA_ATTR,
15833
      ARIA_ATTR: ARIA_ATTR,
15834
      IS_ALLOWED_URI: IS_ALLOWED_URI,
15835
      IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
15836
      ATTR_WHITESPACE: ATTR_WHITESPACE,
15837
      DOCTYPE_NAME: DOCTYPE_NAME
15838
    });
15839
    const getGlobal = () => typeof window === 'undefined' ? null : window;
15840
    const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {
15841
      if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
15842
        return null;
15843
      }
15844
      let suffix = null;
15845
      const ATTR_NAME = 'data-tt-policy-suffix';
15846
      if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
15847
        suffix = purifyHostElement.getAttribute(ATTR_NAME);
15848
      }
15849
      const policyName = 'dompurify' + (suffix ? '#' + suffix : '');
15850
      try {
15851
        return trustedTypes.createPolicy(policyName, {
15852
          createHTML(html) {
15853
            return html;
15854
          },
15855
          createScriptURL(scriptUrl) {
15856
            return scriptUrl;
15857
          }
15858
        });
15859
      } catch (_) {
15860
        console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
15861
        return null;
15862
      }
15863
    };
15864
    function createDOMPurify() {
15865
      let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
15866
      const DOMPurify = root => createDOMPurify(root);
15867
      DOMPurify.version = '3.0.5';
15868
      DOMPurify.removed = [];
15869
      if (!window || !window.document || window.document.nodeType !== 9) {
15870
        DOMPurify.isSupported = false;
15871
        return DOMPurify;
15872
      }
15873
      const originalDocument = window.document;
15874
      const currentScript = originalDocument.currentScript;
15875
      let {document} = window;
15876
      const {DocumentFragment, HTMLTemplateElement, Node, Element, NodeFilter, NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap, HTMLFormElement, DOMParser, trustedTypes} = window;
15877
      const ElementPrototype = Element.prototype;
15878
      const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
15879
      const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
15880
      const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
15881
      const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
15882
      if (typeof HTMLTemplateElement === 'function') {
15883
        const template = document.createElement('template');
15884
        if (template.content && template.content.ownerDocument) {
15885
          document = template.content.ownerDocument;
15886
        }
15887
      }
15888
      let trustedTypesPolicy;
15889
      let emptyHTML = '';
15890
      const {implementation, createNodeIterator, createDocumentFragment, getElementsByTagName} = document;
15891
      const {importNode} = originalDocument;
15892
      let hooks = {};
15893
      DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
15894
      const {MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR, DATA_ATTR, ARIA_ATTR, IS_SCRIPT_OR_DATA, ATTR_WHITESPACE} = EXPRESSIONS;
15895
      let {IS_ALLOWED_URI: IS_ALLOWED_URI$1} = EXPRESSIONS;
15896
      let ALLOWED_TAGS = null;
15897
      const DEFAULT_ALLOWED_TAGS = addToSet({}, [
15898
        ...html$1,
15899
        ...svg$1,
15900
        ...svgFilters,
15901
        ...mathMl$1,
15902
        ...text
15903
      ]);
15904
      let ALLOWED_ATTR = null;
15905
      const DEFAULT_ALLOWED_ATTR = addToSet({}, [
15906
        ...html,
15907
        ...svg,
15908
        ...mathMl,
15909
        ...xml
15910
      ]);
15911
      let CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
15912
        tagNameCheck: {
15913
          writable: true,
15914
          configurable: false,
15915
          enumerable: true,
15916
          value: null
15917
        },
15918
        attributeNameCheck: {
15919
          writable: true,
15920
          configurable: false,
15921
          enumerable: true,
15922
          value: null
15923
        },
15924
        allowCustomizedBuiltInElements: {
15925
          writable: true,
15926
          configurable: false,
15927
          enumerable: true,
15928
          value: false
15929
        }
15930
      }));
15931
      let FORBID_TAGS = null;
15932
      let FORBID_ATTR = null;
15933
      let ALLOW_ARIA_ATTR = true;
15934
      let ALLOW_DATA_ATTR = true;
15935
      let ALLOW_UNKNOWN_PROTOCOLS = false;
15936
      let ALLOW_SELF_CLOSE_IN_ATTR = true;
15937
      let SAFE_FOR_TEMPLATES = false;
15938
      let WHOLE_DOCUMENT = false;
15939
      let SET_CONFIG = false;
15940
      let FORCE_BODY = false;
15941
      let RETURN_DOM = false;
15942
      let RETURN_DOM_FRAGMENT = false;
15943
      let RETURN_TRUSTED_TYPE = false;
15944
      let SANITIZE_DOM = true;
15945
      let SANITIZE_NAMED_PROPS = false;
15946
      const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
15947
      let KEEP_CONTENT = true;
15948
      let IN_PLACE = false;
15949
      let USE_PROFILES = {};
15950
      let FORBID_CONTENTS = null;
15951
      const DEFAULT_FORBID_CONTENTS = addToSet({}, [
15952
        'annotation-xml',
15953
        'audio',
15954
        'colgroup',
15955
        'desc',
15956
        'foreignobject',
15957
        'head',
15958
        'iframe',
15959
        'math',
15960
        'mi',
15961
        'mn',
15962
        'mo',
15963
        'ms',
15964
        'mtext',
15965
        'noembed',
15966
        'noframes',
15967
        'noscript',
15968
        'plaintext',
15969
        'script',
15970
        'style',
15971
        'svg',
15972
        'template',
15973
        'thead',
15974
        'title',
15975
        'video',
15976
        'xmp'
15977
      ]);
15978
      let DATA_URI_TAGS = null;
15979
      const DEFAULT_DATA_URI_TAGS = addToSet({}, [
15980
        'audio',
15981
        'video',
15982
        'img',
15983
        'source',
15984
        'image',
15985
        'track'
15986
      ]);
15987
      let URI_SAFE_ATTRIBUTES = null;
15988
      const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [
15989
        'alt',
15990
        'class',
15991
        'for',
15992
        'id',
15993
        'label',
15994
        'name',
15995
        'pattern',
15996
        'placeholder',
15997
        'role',
15998
        'summary',
15999
        'title',
16000
        'value',
16001
        'style',
16002
        'xmlns'
16003
      ]);
16004
      const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
16005
      const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
16006
      const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
16007
      let NAMESPACE = HTML_NAMESPACE;
16008
      let IS_EMPTY_INPUT = false;
16009
      let ALLOWED_NAMESPACES = null;
16010
      const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [
16011
        MATHML_NAMESPACE,
16012
        SVG_NAMESPACE,
16013
        HTML_NAMESPACE
16014
      ], stringToString);
16015
      let PARSER_MEDIA_TYPE;
16016
      const SUPPORTED_PARSER_MEDIA_TYPES = [
16017
        'application/xhtml+xml',
16018
        'text/html'
16019
      ];
16020
      const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
16021
      let transformCaseFunc;
16022
      let CONFIG = null;
16023
      const formElement = document.createElement('form');
16024
      const isRegexOrFunction = function isRegexOrFunction(testValue) {
16025
        return testValue instanceof RegExp || testValue instanceof Function;
16026
      };
16027
      const _parseConfig = function _parseConfig(cfg) {
16028
        if (CONFIG && CONFIG === cfg) {
16029
          return;
16030
        }
16031
        if (!cfg || typeof cfg !== 'object') {
16032
          cfg = {};
16033
        }
16034
        cfg = clone(cfg);
16035
        PARSER_MEDIA_TYPE = SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
16036
        transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
16037
        ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
16038
        ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
16039
        ALLOWED_NAMESPACES = 'ALLOWED_NAMESPACES' in cfg ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
16040
        URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
16041
        DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
16042
        FORBID_CONTENTS = 'FORBID_CONTENTS' in cfg ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
16043
        FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};
16044
        FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
16045
        USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
16046
        ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
16047
        ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
16048
        ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
16049
        ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false;
16050
        SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
16051
        WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
16052
        RETURN_DOM = cfg.RETURN_DOM || false;
16053
        RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
16054
        RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
16055
        FORCE_BODY = cfg.FORCE_BODY || false;
16056
        SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
16057
        SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false;
16058
        KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
16059
        IN_PLACE = cfg.IN_PLACE || false;
16060
        IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;
16061
        NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
16062
        CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
16063
        if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
16064
          CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
16065
        }
16066
        if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {
16067
          CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
16068
        }
16069
        if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {
16070
          CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
16071
        }
16072
        if (SAFE_FOR_TEMPLATES) {
16073
          ALLOW_DATA_ATTR = false;
16074
        }
16075
        if (RETURN_DOM_FRAGMENT) {
16076
          RETURN_DOM = true;
16077
        }
16078
        if (USE_PROFILES) {
16079
          ALLOWED_TAGS = addToSet({}, [...text]);
16080
          ALLOWED_ATTR = [];
16081
          if (USE_PROFILES.html === true) {
16082
            addToSet(ALLOWED_TAGS, html$1);
16083
            addToSet(ALLOWED_ATTR, html);
16084
          }
16085
          if (USE_PROFILES.svg === true) {
16086
            addToSet(ALLOWED_TAGS, svg$1);
16087
            addToSet(ALLOWED_ATTR, svg);
16088
            addToSet(ALLOWED_ATTR, xml);
16089
          }
16090
          if (USE_PROFILES.svgFilters === true) {
16091
            addToSet(ALLOWED_TAGS, svgFilters);
16092
            addToSet(ALLOWED_ATTR, svg);
16093
            addToSet(ALLOWED_ATTR, xml);
16094
          }
16095
          if (USE_PROFILES.mathMl === true) {
16096
            addToSet(ALLOWED_TAGS, mathMl$1);
16097
            addToSet(ALLOWED_ATTR, mathMl);
16098
            addToSet(ALLOWED_ATTR, xml);
16099
          }
16100
        }
16101
        if (cfg.ADD_TAGS) {
16102
          if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
16103
            ALLOWED_TAGS = clone(ALLOWED_TAGS);
16104
          }
16105
          addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
16106
        }
16107
        if (cfg.ADD_ATTR) {
16108
          if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
16109
            ALLOWED_ATTR = clone(ALLOWED_ATTR);
16110
          }
16111
          addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
16112
        }
16113
        if (cfg.ADD_URI_SAFE_ATTR) {
16114
          addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
16115
        }
16116
        if (cfg.FORBID_CONTENTS) {
16117
          if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
16118
            FORBID_CONTENTS = clone(FORBID_CONTENTS);
16119
          }
16120
          addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
16121
        }
16122
        if (KEEP_CONTENT) {
16123
          ALLOWED_TAGS['#text'] = true;
16124
        }
16125
        if (WHOLE_DOCUMENT) {
16126
          addToSet(ALLOWED_TAGS, [
16127
            'html',
16128
            'head',
16129
            'body'
16130
          ]);
16131
        }
16132
        if (ALLOWED_TAGS.table) {
16133
          addToSet(ALLOWED_TAGS, ['tbody']);
16134
          delete FORBID_TAGS.tbody;
16135
        }
16136
        if (cfg.TRUSTED_TYPES_POLICY) {
16137
          if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {
16138
            throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
16139
          }
16140
          if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {
16141
            throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
16142
          }
16143
          trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
16144
          emptyHTML = trustedTypesPolicy.createHTML('');
16145
        } else {
16146
          if (trustedTypesPolicy === undefined) {
16147
            trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
16148
          }
16149
          if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {
16150
            emptyHTML = trustedTypesPolicy.createHTML('');
16151
          }
16152
        }
16153
        if (freeze) {
16154
          freeze(cfg);
16155
        }
16156
        CONFIG = cfg;
16157
      };
16158
      const MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [
16159
        'mi',
16160
        'mo',
16161
        'mn',
16162
        'ms',
16163
        'mtext'
16164
      ]);
16165
      const HTML_INTEGRATION_POINTS = addToSet({}, [
16166
        'foreignobject',
16167
        'desc',
16168
        'title',
16169
        'annotation-xml'
16170
      ]);
16171
      const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [
16172
        'title',
16173
        'style',
16174
        'font',
16175
        'a',
16176
        'script'
16177
      ]);
16178
      const ALL_SVG_TAGS = addToSet({}, svg$1);
16179
      addToSet(ALL_SVG_TAGS, svgFilters);
16180
      addToSet(ALL_SVG_TAGS, svgDisallowed);
16181
      const ALL_MATHML_TAGS = addToSet({}, mathMl$1);
16182
      addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
16183
      const _checkValidNamespace = function _checkValidNamespace(element) {
16184
        let parent = getParentNode(element);
16185
        if (!parent || !parent.tagName) {
16186
          parent = {
16187
            namespaceURI: NAMESPACE,
16188
            tagName: 'template'
16189
          };
16190
        }
16191
        const tagName = stringToLowerCase(element.tagName);
16192
        const parentTagName = stringToLowerCase(parent.tagName);
16193
        if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
16194
          return false;
16195
        }
16196
        if (element.namespaceURI === SVG_NAMESPACE) {
16197
          if (parent.namespaceURI === HTML_NAMESPACE) {
16198
            return tagName === 'svg';
16199
          }
16200
          if (parent.namespaceURI === MATHML_NAMESPACE) {
16201
            return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
16202
          }
16203
          return Boolean(ALL_SVG_TAGS[tagName]);
16204
        }
16205
        if (element.namespaceURI === MATHML_NAMESPACE) {
16206
          if (parent.namespaceURI === HTML_NAMESPACE) {
16207
            return tagName === 'math';
16208
          }
16209
          if (parent.namespaceURI === SVG_NAMESPACE) {
16210
            return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
16211
          }
16212
          return Boolean(ALL_MATHML_TAGS[tagName]);
16213
        }
16214
        if (element.namespaceURI === HTML_NAMESPACE) {
16215
          if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
16216
            return false;
16217
          }
16218
          if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
16219
            return false;
16220
          }
16221
          return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
16222
        }
16223
        if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
16224
          return true;
16225
        }
16226
        return false;
16227
      };
16228
      const _forceRemove = function _forceRemove(node) {
16229
        arrayPush(DOMPurify.removed, { element: node });
16230
        try {
16231
          node.parentNode.removeChild(node);
16232
        } catch (_) {
16233
          node.remove();
16234
        }
16235
      };
16236
      const _removeAttribute = function _removeAttribute(name, node) {
16237
        try {
16238
          arrayPush(DOMPurify.removed, {
16239
            attribute: node.getAttributeNode(name),
16240
            from: node
16241
          });
16242
        } catch (_) {
16243
          arrayPush(DOMPurify.removed, {
16244
            attribute: null,
16245
            from: node
16246
          });
16247
        }
16248
        node.removeAttribute(name);
16249
        if (name === 'is' && !ALLOWED_ATTR[name]) {
16250
          if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
16251
            try {
16252
              _forceRemove(node);
16253
            } catch (_) {
16254
            }
16255
          } else {
16256
            try {
16257
              node.setAttribute(name, '');
16258
            } catch (_) {
16259
            }
16260
          }
16261
        }
16262
      };
16263
      const _initDocument = function _initDocument(dirty) {
16264
        let doc;
16265
        let leadingWhitespace;
16266
        if (FORCE_BODY) {
16267
          dirty = '<remove></remove>' + dirty;
16268
        } else {
16269
          const matches = stringMatch(dirty, /^[\r\n\t ]+/);
16270
          leadingWhitespace = matches && matches[0];
16271
        }
16272
        if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {
16273
          dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
16274
        }
16275
        const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;
16276
        if (NAMESPACE === HTML_NAMESPACE) {
16277
          try {
16278
            doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
16279
          } catch (_) {
16280
          }
16281
        }
16282
        if (!doc || !doc.documentElement) {
16283
          doc = implementation.createDocument(NAMESPACE, 'template', null);
16284
          try {
16285
            doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
16286
          } catch (_) {
16287
          }
16288
        }
16289
        const body = doc.body || doc.documentElement;
16290
        if (dirty && leadingWhitespace) {
16291
          body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
16292
        }
16293
        if (NAMESPACE === HTML_NAMESPACE) {
16294
          return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
16295
        }
16296
        return WHOLE_DOCUMENT ? doc.documentElement : body;
16297
      };
16298
      const _createIterator = function _createIterator(root) {
16299
        return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
16300
      };
16301
      const _isClobbered = function _isClobbered(elm) {
16302
        return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');
16303
      };
16304
      const _isNode = function _isNode(object) {
16305
        return typeof Node === 'object' ? object instanceof Node : object && typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
16306
      };
16307
      const _executeHook = function _executeHook(entryPoint, currentNode, data) {
16308
        if (!hooks[entryPoint]) {
16309
          return;
16310
        }
16311
        arrayForEach(hooks[entryPoint], hook => {
16312
          hook.call(DOMPurify, currentNode, data, CONFIG);
16313
        });
16314
      };
16315
      const _sanitizeElements = function _sanitizeElements(currentNode) {
16316
        let content;
16317
        _executeHook('beforeSanitizeElements', currentNode, null);
16318
        if (_isClobbered(currentNode)) {
16319
          _forceRemove(currentNode);
16320
          return true;
16321
        }
16322
        const tagName = transformCaseFunc(currentNode.nodeName);
16323
        _executeHook('uponSanitizeElement', currentNode, {
16324
          tagName,
16325
          allowedTags: ALLOWED_TAGS
16326
        });
16327
        if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
16328
          _forceRemove(currentNode);
16329
          return true;
16330
        }
16331
        if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
16332
          if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
16333
            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName))
16334
              return false;
16335
            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName))
16336
              return false;
16337
          }
16338
          if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
16339
            const parentNode = getParentNode(currentNode) || currentNode.parentNode;
16340
            const childNodes = getChildNodes(currentNode) || currentNode.childNodes;
16341
            if (childNodes && parentNode) {
16342
              const childCount = childNodes.length;
16343
              for (let i = childCount - 1; i >= 0; --i) {
16344
                parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));
16345
              }
16346
            }
16347
          }
16348
          _forceRemove(currentNode);
16349
          return true;
16350
        }
16351
        if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
16352
          _forceRemove(currentNode);
16353
          return true;
16354
        }
16355
        if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
16356
          _forceRemove(currentNode);
16357
          return true;
16358
        }
16359
        if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
16360
          content = currentNode.textContent;
16361
          content = stringReplace(content, MUSTACHE_EXPR, ' ');
16362
          content = stringReplace(content, ERB_EXPR, ' ');
16363
          content = stringReplace(content, TMPLIT_EXPR, ' ');
16364
          if (currentNode.textContent !== content) {
16365
            arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
16366
            currentNode.textContent = content;
16367
          }
16368
        }
16369
        _executeHook('afterSanitizeElements', currentNode, null);
16370
        return false;
16371
      };
16372
      const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
16373
        if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
16374
          return false;
16375
        }
16376
        if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName));
16377
        else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName));
16378
        else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
16379
          if (_basicCustomElementTest(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) || lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value)));
16380
          else {
16381
            return false;
16382
          }
16383
        } else if (URI_SAFE_ATTRIBUTES[lcName]);
16384
        else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, '')));
16385
        else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]);
16386
        else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, '')));
16387
        else if (value) {
16388
          return false;
16389
        } else ;
16390
        return true;
16391
      };
16392
      const _basicCustomElementTest = function _basicCustomElementTest(tagName) {
16393
        return tagName.indexOf('-') > 0;
16394
      };
16395
      const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
16396
        let attr;
16397
        let value;
16398
        let lcName;
16399
        let l;
16400
        _executeHook('beforeSanitizeAttributes', currentNode, null);
16401
        const {attributes} = currentNode;
16402
        if (!attributes) {
16403
          return;
16404
        }
16405
        const hookEvent = {
16406
          attrName: '',
16407
          attrValue: '',
16408
          keepAttr: true,
16409
          allowedAttributes: ALLOWED_ATTR
16410
        };
16411
        l = attributes.length;
16412
        while (l--) {
16413
          attr = attributes[l];
16414
          const {name, namespaceURI} = attr;
16415
          value = name === 'value' ? attr.value : stringTrim(attr.value);
16416
          const initValue = value;
16417
          lcName = transformCaseFunc(name);
16418
          hookEvent.attrName = lcName;
16419
          hookEvent.attrValue = value;
16420
          hookEvent.keepAttr = true;
16421
          hookEvent.forceKeepAttr = undefined;
16422
          _executeHook('uponSanitizeAttribute', currentNode, hookEvent);
16423
          value = hookEvent.attrValue;
16424
          if (hookEvent.forceKeepAttr) {
16425
            continue;
16426
          }
16427
          if (!hookEvent.keepAttr) {
16428
            _removeAttribute(name, currentNode);
16429
            continue;
16430
          }
16431
          if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
16432
            _removeAttribute(name, currentNode);
16433
            continue;
16434
          }
16435
          if (SAFE_FOR_TEMPLATES) {
16436
            value = stringReplace(value, MUSTACHE_EXPR, ' ');
16437
            value = stringReplace(value, ERB_EXPR, ' ');
16438
            value = stringReplace(value, TMPLIT_EXPR, ' ');
16439
          }
16440
          const lcTag = transformCaseFunc(currentNode.nodeName);
16441
          if (!_isValidAttribute(lcTag, lcName, value)) {
16442
            _removeAttribute(name, currentNode);
16443
            continue;
16444
          }
16445
          if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
16446
            _removeAttribute(name, currentNode);
16447
            value = SANITIZE_NAMED_PROPS_PREFIX + value;
16448
          }
16449
          if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {
16450
            if (namespaceURI);
16451
            else {
16452
              switch (trustedTypes.getAttributeType(lcTag, lcName)) {
16453
              case 'TrustedHTML': {
16454
                  value = trustedTypesPolicy.createHTML(value);
16455
                  break;
16456
                }
16457
              case 'TrustedScriptURL': {
16458
                  value = trustedTypesPolicy.createScriptURL(value);
16459
                  break;
16460
                }
16461
              }
16462
            }
16463
          }
16464
          if (value !== initValue) {
16465
            try {
16466
              if (namespaceURI) {
16467
                currentNode.setAttributeNS(namespaceURI, name, value);
16468
              } else {
16469
                currentNode.setAttribute(name, value);
16470
              }
16471
            } catch (_) {
16472
              _removeAttribute(name, currentNode);
16473
            }
16474
          }
16475
        }
16476
        _executeHook('afterSanitizeAttributes', currentNode, null);
16477
      };
16478
      const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
16479
        let shadowNode;
16480
        const shadowIterator = _createIterator(fragment);
16481
        _executeHook('beforeSanitizeShadowDOM', fragment, null);
16482
        while (shadowNode = shadowIterator.nextNode()) {
16483
          _executeHook('uponSanitizeShadowNode', shadowNode, null);
16484
          if (_sanitizeElements(shadowNode)) {
16485
            continue;
16486
          }
16487
          if (shadowNode.content instanceof DocumentFragment) {
16488
            _sanitizeShadowDOM(shadowNode.content);
16489
          }
16490
          _sanitizeAttributes(shadowNode);
16491
        }
16492
        _executeHook('afterSanitizeShadowDOM', fragment, null);
16493
      };
16494
      DOMPurify.sanitize = function (dirty) {
16495
        let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
16496
        let body;
16497
        let importedNode;
16498
        let currentNode;
16499
        let returnNode;
16500
        IS_EMPTY_INPUT = !dirty;
16501
        if (IS_EMPTY_INPUT) {
16502
          dirty = '<!-->';
16503
        }
16504
        if (typeof dirty !== 'string' && !_isNode(dirty)) {
16505
          if (typeof dirty.toString === 'function') {
16506
            dirty = dirty.toString();
16507
            if (typeof dirty !== 'string') {
16508
              throw typeErrorCreate('dirty is not a string, aborting');
16509
            }
16510
          } else {
16511
            throw typeErrorCreate('toString is not a function');
16512
          }
16513
        }
16514
        if (!DOMPurify.isSupported) {
16515
          return dirty;
16516
        }
16517
        if (!SET_CONFIG) {
16518
          _parseConfig(cfg);
16519
        }
16520
        DOMPurify.removed = [];
16521
        if (typeof dirty === 'string') {
16522
          IN_PLACE = false;
16523
        }
16524
        if (IN_PLACE) {
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
          body = _initDocument('<!---->');
16533
          importedNode = body.ownerDocument.importNode(dirty, true);
16534
          if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {
16535
            body = importedNode;
16536
          } else if (importedNode.nodeName === 'HTML') {
16537
            body = importedNode;
16538
          } else {
16539
            body.appendChild(importedNode);
16540
          }
16541
        } else {
16542
          if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
16543
            return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
16544
          }
16545
          body = _initDocument(dirty);
16546
          if (!body) {
16547
            return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
16548
          }
16549
        }
16550
        if (body && FORCE_BODY) {
16551
          _forceRemove(body.firstChild);
16552
        }
16553
        const nodeIterator = _createIterator(IN_PLACE ? dirty : body);
16554
        while (currentNode = nodeIterator.nextNode()) {
16555
          if (_sanitizeElements(currentNode)) {
16556
            continue;
16557
          }
16558
          if (currentNode.content instanceof DocumentFragment) {
16559
            _sanitizeShadowDOM(currentNode.content);
16560
          }
16561
          _sanitizeAttributes(currentNode);
16562
        }
16563
        if (IN_PLACE) {
16564
          return dirty;
16565
        }
16566
        if (RETURN_DOM) {
16567
          if (RETURN_DOM_FRAGMENT) {
16568
            returnNode = createDocumentFragment.call(body.ownerDocument);
16569
            while (body.firstChild) {
16570
              returnNode.appendChild(body.firstChild);
16571
            }
16572
          } else {
16573
            returnNode = body;
16574
          }
16575
          if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {
16576
            returnNode = importNode.call(originalDocument, returnNode, true);
16577
          }
16578
          return returnNode;
16579
        }
16580
        let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
16581
        if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
16582
          serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
16583
        }
16584
        if (SAFE_FOR_TEMPLATES) {
16585
          serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR, ' ');
16586
          serializedHTML = stringReplace(serializedHTML, ERB_EXPR, ' ');
16587
          serializedHTML = stringReplace(serializedHTML, TMPLIT_EXPR, ' ');
16588
        }
16589
        return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
16590
      };
16591
      DOMPurify.setConfig = function (cfg) {
16592
        _parseConfig(cfg);
16593
        SET_CONFIG = true;
16594
      };
16595
      DOMPurify.clearConfig = function () {
16596
        CONFIG = null;
16597
        SET_CONFIG = false;
16598
      };
16599
      DOMPurify.isValidAttribute = function (tag, attr, value) {
16600
        if (!CONFIG) {
16601
          _parseConfig({});
16602
        }
16603
        const lcTag = transformCaseFunc(tag);
16604
        const lcName = transformCaseFunc(attr);
16605
        return _isValidAttribute(lcTag, lcName, value);
16606
      };
16607
      DOMPurify.addHook = function (entryPoint, hookFunction) {
16608
        if (typeof hookFunction !== 'function') {
16609
          return;
16610
        }
16611
        hooks[entryPoint] = hooks[entryPoint] || [];
16612
        arrayPush(hooks[entryPoint], hookFunction);
16613
      };
16614
      DOMPurify.removeHook = function (entryPoint) {
16615
        if (hooks[entryPoint]) {
16616
          return arrayPop(hooks[entryPoint]);
16617
        }
16618
      };
16619
      DOMPurify.removeHooks = function (entryPoint) {
16620
        if (hooks[entryPoint]) {
16621
          hooks[entryPoint] = [];
16622
        }
16623
      };
16624
      DOMPurify.removeAllHooks = function () {
16625
        hooks = {};
16626
      };
16627
      return DOMPurify;
16628
    }
16629
    var purify = createDOMPurify();
16630
 
16631
    const each$4 = Tools.each, trim = Tools.trim;
16632
    const queryParts = [
16633
      'source',
16634
      'protocol',
16635
      'authority',
16636
      'userInfo',
16637
      'user',
16638
      'password',
16639
      'host',
16640
      'port',
16641
      'relative',
16642
      'path',
16643
      'directory',
16644
      'file',
16645
      'query',
16646
      'anchor'
16647
    ];
16648
    const DEFAULT_PORTS = {
16649
      ftp: 21,
16650
      http: 80,
16651
      https: 443,
16652
      mailto: 25
16653
    };
16654
    const safeSvgDataUrlElements = [
16655
      'img',
16656
      'video'
16657
    ];
16658
    const blockSvgDataUris = (allowSvgDataUrls, tagName) => {
16659
      if (isNonNullable(allowSvgDataUrls)) {
16660
        return !allowSvgDataUrls;
16661
      } else {
16662
        return isNonNullable(tagName) ? !contains$2(safeSvgDataUrlElements, tagName) : true;
16663
      }
16664
    };
16665
    const decodeUri = encodedUri => {
16666
      try {
16667
        return decodeURIComponent(encodedUri);
16668
      } catch (ex) {
16669
        return unescape(encodedUri);
16670
      }
16671
    };
16672
    const isInvalidUri = (settings, uri, tagName) => {
16673
      const decodedUri = decodeUri(uri).replace(/\s/g, '');
16674
      if (settings.allow_script_urls) {
16675
        return false;
16676
      } else if (/((java|vb)script|mhtml):/i.test(decodedUri)) {
16677
        return true;
16678
      } else if (settings.allow_html_data_urls) {
16679
        return false;
16680
      } else if (/^data:image\//i.test(decodedUri)) {
16681
        return blockSvgDataUris(settings.allow_svg_data_urls, tagName) && /^data:image\/svg\+xml/i.test(decodedUri);
16682
      } else {
16683
        return /^data:/i.test(decodedUri);
16684
      }
16685
    };
16686
    class URI {
16687
      static parseDataUri(uri) {
16688
        let type;
16689
        const uriComponents = decodeURIComponent(uri).split(',');
16690
        const matches = /data:([^;]+)/.exec(uriComponents[0]);
16691
        if (matches) {
16692
          type = matches[1];
16693
        }
16694
        return {
16695
          type,
16696
          data: uriComponents[1]
16697
        };
16698
      }
16699
      static isDomSafe(uri, context, options = {}) {
16700
        if (options.allow_script_urls) {
16701
          return true;
16702
        } else {
16703
          const decodedUri = Entities.decode(uri).replace(/[\s\u0000-\u001F]+/g, '');
16704
          return !isInvalidUri(options, decodedUri, context);
16705
        }
16706
      }
16707
      static getDocumentBaseUrl(loc) {
16708
        var _a;
16709
        let baseUrl;
16710
        if (loc.protocol.indexOf('http') !== 0 && loc.protocol !== 'file:') {
16711
          baseUrl = (_a = loc.href) !== null && _a !== void 0 ? _a : '';
16712
        } else {
16713
          baseUrl = loc.protocol + '//' + loc.host + loc.pathname;
16714
        }
16715
        if (/^[^:]+:\/\/\/?[^\/]+\//.test(baseUrl)) {
16716
          baseUrl = baseUrl.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
16717
          if (!/[\/\\]$/.test(baseUrl)) {
16718
            baseUrl += '/';
16719
          }
16720
        }
16721
        return baseUrl;
16722
      }
16723
      constructor(url, settings = {}) {
16724
        this.path = '';
16725
        this.directory = '';
16726
        url = trim(url);
16727
        this.settings = settings;
16728
        const baseUri = settings.base_uri;
16729
        const self = this;
16730
        if (/^([\w\-]+):([^\/]{2})/i.test(url) || /^\s*#/.test(url)) {
16731
          self.source = url;
16732
          return;
16733
        }
16734
        const isProtocolRelative = url.indexOf('//') === 0;
16735
        if (url.indexOf('/') === 0 && !isProtocolRelative) {
16736
          url = (baseUri ? baseUri.protocol || 'http' : 'http') + '://mce_host' + url;
16737
        }
16738
        if (!/^[\w\-]*:?\/\//.test(url)) {
16739
          const baseUrl = baseUri ? baseUri.path : new URI(document.location.href).directory;
16740
          if ((baseUri === null || baseUri === void 0 ? void 0 : baseUri.protocol) === '') {
16741
            url = '//mce_host' + self.toAbsPath(baseUrl, url);
16742
          } else {
16743
            const match = /([^#?]*)([#?]?.*)/.exec(url);
16744
            if (match) {
16745
              url = (baseUri && baseUri.protocol || 'http') + '://mce_host' + self.toAbsPath(baseUrl, match[1]) + match[2];
16746
            }
16747
          }
16748
        }
16749
        url = url.replace(/@@/g, '(mce_at)');
16750
        const urlMatch = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?(\[[a-zA-Z0-9:.%]+\]|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(url);
16751
        if (urlMatch) {
16752
          each$4(queryParts, (v, i) => {
16753
            let part = urlMatch[i];
16754
            if (part) {
16755
              part = part.replace(/\(mce_at\)/g, '@@');
16756
            }
16757
            self[v] = part;
16758
          });
16759
        }
16760
        if (baseUri) {
16761
          if (!self.protocol) {
16762
            self.protocol = baseUri.protocol;
16763
          }
16764
          if (!self.userInfo) {
16765
            self.userInfo = baseUri.userInfo;
16766
          }
16767
          if (!self.port && self.host === 'mce_host') {
16768
            self.port = baseUri.port;
16769
          }
16770
          if (!self.host || self.host === 'mce_host') {
16771
            self.host = baseUri.host;
16772
          }
16773
          self.source = '';
16774
        }
16775
        if (isProtocolRelative) {
16776
          self.protocol = '';
16777
        }
16778
      }
16779
      setPath(path) {
16780
        const pathMatch = /^(.*?)\/?(\w+)?$/.exec(path);
16781
        if (pathMatch) {
16782
          this.path = pathMatch[0];
16783
          this.directory = pathMatch[1];
16784
          this.file = pathMatch[2];
16785
        }
16786
        this.source = '';
16787
        this.getURI();
16788
      }
16789
      toRelative(uri) {
16790
        if (uri === './') {
16791
          return uri;
16792
        }
16793
        const relativeUri = new URI(uri, { base_uri: this });
16794
        if (relativeUri.host !== 'mce_host' && this.host !== relativeUri.host && relativeUri.host || this.port !== relativeUri.port || this.protocol !== relativeUri.protocol && relativeUri.protocol !== '') {
16795
          return relativeUri.getURI();
16796
        }
16797
        const tu = this.getURI(), uu = relativeUri.getURI();
16798
        if (tu === uu || tu.charAt(tu.length - 1) === '/' && tu.substr(0, tu.length - 1) === uu) {
16799
          return tu;
16800
        }
16801
        let output = this.toRelPath(this.path, relativeUri.path);
16802
        if (relativeUri.query) {
16803
          output += '?' + relativeUri.query;
16804
        }
16805
        if (relativeUri.anchor) {
16806
          output += '#' + relativeUri.anchor;
16807
        }
16808
        return output;
16809
      }
16810
      toAbsolute(uri, noHost) {
16811
        const absoluteUri = new URI(uri, { base_uri: this });
16812
        return absoluteUri.getURI(noHost && this.isSameOrigin(absoluteUri));
16813
      }
16814
      isSameOrigin(uri) {
16815
        if (this.host == uri.host && this.protocol == uri.protocol) {
16816
          if (this.port == uri.port) {
16817
            return true;
16818
          }
16819
          const defaultPort = this.protocol ? DEFAULT_PORTS[this.protocol] : null;
16820
          if (defaultPort && (this.port || defaultPort) == (uri.port || defaultPort)) {
16821
            return true;
16822
          }
16823
        }
16824
        return false;
16825
      }
16826
      toRelPath(base, path) {
16827
        let breakPoint = 0, out = '', i, l;
16828
        const normalizedBase = base.substring(0, base.lastIndexOf('/')).split('/');
16829
        const items = path.split('/');
16830
        if (normalizedBase.length >= items.length) {
16831
          for (i = 0, l = normalizedBase.length; i < l; i++) {
16832
            if (i >= items.length || normalizedBase[i] !== items[i]) {
16833
              breakPoint = i + 1;
16834
              break;
16835
            }
16836
          }
16837
        }
16838
        if (normalizedBase.length < items.length) {
16839
          for (i = 0, l = items.length; i < l; i++) {
16840
            if (i >= normalizedBase.length || normalizedBase[i] !== items[i]) {
16841
              breakPoint = i + 1;
16842
              break;
16843
            }
16844
          }
16845
        }
16846
        if (breakPoint === 1) {
16847
          return path;
16848
        }
16849
        for (i = 0, l = normalizedBase.length - (breakPoint - 1); i < l; i++) {
16850
          out += '../';
16851
        }
16852
        for (i = breakPoint - 1, l = items.length; i < l; i++) {
16853
          if (i !== breakPoint - 1) {
16854
            out += '/' + items[i];
16855
          } else {
16856
            out += items[i];
16857
          }
16858
        }
16859
        return out;
16860
      }
16861
      toAbsPath(base, path) {
16862
        let nb = 0;
16863
        const tr = /\/$/.test(path) ? '/' : '';
16864
        const normalizedBase = base.split('/');
16865
        const normalizedPath = path.split('/');
16866
        const baseParts = [];
16867
        each$4(normalizedBase, k => {
16868
          if (k) {
16869
            baseParts.push(k);
16870
          }
16871
        });
16872
        const pathParts = [];
16873
        for (let i = normalizedPath.length - 1; i >= 0; i--) {
16874
          if (normalizedPath[i].length === 0 || normalizedPath[i] === '.') {
16875
            continue;
16876
          }
16877
          if (normalizedPath[i] === '..') {
16878
            nb++;
16879
            continue;
16880
          }
16881
          if (nb > 0) {
16882
            nb--;
16883
            continue;
16884
          }
16885
          pathParts.push(normalizedPath[i]);
16886
        }
16887
        const i = baseParts.length - nb;
16888
        let outPath;
16889
        if (i <= 0) {
16890
          outPath = reverse(pathParts).join('/');
16891
        } else {
16892
          outPath = baseParts.slice(0, i).join('/') + '/' + reverse(pathParts).join('/');
16893
        }
16894
        if (outPath.indexOf('/') !== 0) {
16895
          outPath = '/' + outPath;
16896
        }
16897
        if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) {
16898
          outPath += tr;
16899
        }
16900
        return outPath;
16901
      }
16902
      getURI(noProtoHost = false) {
16903
        let s;
16904
        if (!this.source || noProtoHost) {
16905
          s = '';
16906
          if (!noProtoHost) {
16907
            if (this.protocol) {
16908
              s += this.protocol + '://';
16909
            } else {
16910
              s += '//';
16911
            }
16912
            if (this.userInfo) {
16913
              s += this.userInfo + '@';
16914
            }
16915
            if (this.host) {
16916
              s += this.host;
16917
            }
16918
            if (this.port) {
16919
              s += ':' + this.port;
16920
            }
16921
          }
16922
          if (this.path) {
16923
            s += this.path;
16924
          }
16925
          if (this.query) {
16926
            s += '?' + this.query;
16927
          }
16928
          if (this.anchor) {
16929
            s += '#' + this.anchor;
16930
          }
16931
          this.source = s;
16932
        }
16933
        return this.source;
16934
      }
16935
    }
16936
 
16937
    const filteredUrlAttrs = Tools.makeMap('src,href,data,background,action,formaction,poster,xlink:href');
16938
    const internalElementAttr = 'data-mce-type';
16939
    let uid = 0;
16940
    const processNode = (node, settings, schema, scope, evt) => {
16941
      var _a, _b, _c, _d;
16942
      const validate = settings.validate;
16943
      const specialElements = schema.getSpecialElements();
16944
      if (node.nodeType === COMMENT && !settings.allow_conditional_comments && /^\[if/i.test((_a = node.nodeValue) !== null && _a !== void 0 ? _a : '')) {
16945
        node.nodeValue = ' ' + node.nodeValue;
16946
      }
16947
      const lcTagName = (_b = evt === null || evt === void 0 ? void 0 : evt.tagName) !== null && _b !== void 0 ? _b : node.nodeName.toLowerCase();
16948
      if (scope !== 'html' && schema.isValid(scope)) {
16949
        if (isNonNullable(evt)) {
16950
          evt.allowedTags[lcTagName] = true;
16951
        }
16952
        return;
16953
      }
16954
      if (node.nodeType !== ELEMENT || lcTagName === 'body') {
16955
        return;
16956
      }
16957
      const element = SugarElement.fromDom(node);
16958
      const isInternalElement = has$1(element, internalElementAttr);
16959
      const bogus = get$9(element, 'data-mce-bogus');
16960
      if (!isInternalElement && isString(bogus)) {
16961
        if (bogus === 'all') {
16962
          remove$5(element);
16963
        } else {
16964
          unwrap(element);
16965
        }
16966
        return;
16967
      }
16968
      const rule = schema.getElementRule(lcTagName);
16969
      if (validate && !rule) {
16970
        if (has$2(specialElements, lcTagName)) {
16971
          remove$5(element);
16972
        } else {
16973
          unwrap(element);
16974
        }
16975
        return;
16976
      } else {
16977
        if (isNonNullable(evt)) {
16978
          evt.allowedTags[lcTagName] = true;
16979
        }
16980
      }
16981
      if (validate && rule && !isInternalElement) {
16982
        each$e((_c = rule.attributesForced) !== null && _c !== void 0 ? _c : [], attr => {
16983
          set$3(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
16984
        });
16985
        each$e((_d = rule.attributesDefault) !== null && _d !== void 0 ? _d : [], attr => {
16986
          if (!has$1(element, attr.name)) {
16987
            set$3(element, attr.name, attr.value === '{$uid}' ? `mce_${ uid++ }` : attr.value);
16988
          }
16989
        });
16990
        if (rule.attributesRequired && !exists(rule.attributesRequired, attr => has$1(element, attr))) {
16991
          unwrap(element);
16992
          return;
16993
        }
16994
        if (rule.removeEmptyAttrs && hasNone(element)) {
16995
          unwrap(element);
16996
          return;
16997
        }
16998
        if (rule.outputName && rule.outputName !== lcTagName) {
16999
          mutate(element, rule.outputName);
17000
        }
17001
      }
17002
    };
17003
    const processAttr = (ele, settings, schema, scope, evt) => {
17004
      const tagName = ele.tagName.toLowerCase();
17005
      const {attrName, attrValue} = evt;
17006
      evt.keepAttr = shouldKeepAttribute(settings, schema, scope, tagName, attrName, attrValue);
17007
      if (evt.keepAttr) {
17008
        evt.allowedAttributes[attrName] = true;
17009
        if (isBooleanAttribute(attrName, schema)) {
17010
          evt.attrValue = attrName;
17011
        }
17012
        if (settings.allow_svg_data_urls && startsWith(attrValue, 'data:image/svg+xml')) {
17013
          evt.forceKeepAttr = true;
17014
        }
17015
      } else if (isRequiredAttributeOfInternalElement(ele, attrName)) {
17016
        evt.forceKeepAttr = true;
17017
      }
17018
    };
17019
    const shouldKeepAttribute = (settings, schema, scope, tagName, attrName, attrValue) => {
17020
      if (scope !== 'html' && !isNonHtmlElementRootName(tagName)) {
17021
        return true;
17022
      }
17023
      return !(attrName in filteredUrlAttrs && isInvalidUri(settings, attrValue, tagName)) && (!settings.validate || schema.isValid(tagName, attrName) || startsWith(attrName, 'data-') || startsWith(attrName, 'aria-'));
17024
    };
17025
    const isRequiredAttributeOfInternalElement = (ele, attrName) => ele.hasAttribute(internalElementAttr) && (attrName === 'id' || attrName === 'class' || attrName === 'style');
17026
    const isBooleanAttribute = (attrName, schema) => attrName in schema.getBoolAttrs();
17027
    const filterAttributes = (ele, settings, schema, scope) => {
17028
      const {attributes} = ele;
17029
      for (let i = attributes.length - 1; i >= 0; i--) {
17030
        const attr = attributes[i];
17031
        const attrName = attr.name;
17032
        const attrValue = attr.value;
17033
        if (!shouldKeepAttribute(settings, schema, scope, ele.tagName.toLowerCase(), attrName, attrValue) && !isRequiredAttributeOfInternalElement(ele, attrName)) {
17034
          ele.removeAttribute(attrName);
17035
        } else if (isBooleanAttribute(attrName, schema)) {
17036
          ele.setAttribute(attrName, attrName);
17037
        }
17038
      }
17039
    };
17040
    const setupPurify = (settings, schema, namespaceTracker) => {
17041
      const purify$1 = purify();
17042
      purify$1.addHook('uponSanitizeElement', (ele, evt) => {
17043
        processNode(ele, settings, schema, namespaceTracker.track(ele), evt);
17044
      });
17045
      purify$1.addHook('uponSanitizeAttribute', (ele, evt) => {
17046
        processAttr(ele, settings, schema, namespaceTracker.current(), evt);
17047
      });
17048
      return purify$1;
17049
    };
17050
    const getPurifyConfig = (settings, mimeType) => {
17051
      const basePurifyConfig = {
17052
        IN_PLACE: true,
17053
        ALLOW_UNKNOWN_PROTOCOLS: true,
17054
        ALLOWED_TAGS: [
17055
          '#comment',
17056
          '#cdata-section',
17057
          'body'
17058
        ],
17059
        ALLOWED_ATTR: []
17060
      };
17061
      const config = { ...basePurifyConfig };
17062
      config.PARSER_MEDIA_TYPE = mimeType;
17063
      if (settings.allow_script_urls) {
17064
        config.ALLOWED_URI_REGEXP = /.*/;
17065
      } else if (settings.allow_html_data_urls) {
17066
        config.ALLOWED_URI_REGEXP = /^(?!(\w+script|mhtml):)/i;
17067
      }
17068
      return config;
17069
    };
17070
    const sanitizeNamespaceElement = ele => {
17071
      const xlinkAttrs = [
17072
        'type',
17073
        'href',
17074
        'role',
17075
        'arcrole',
17076
        'title',
17077
        'show',
17078
        'actuate',
17079
        'label',
17080
        'from',
17081
        'to'
17082
      ].map(name => `xlink:${ name }`);
17083
      const config = {
17084
        IN_PLACE: true,
17085
        USE_PROFILES: {
17086
          html: true,
17087
          svg: true,
17088
          svgFilters: true
17089
        },
17090
        ALLOWED_ATTR: xlinkAttrs
17091
      };
17092
      purify().sanitize(ele, config);
17093
      return ele.innerHTML;
17094
    };
17095
    const getSanitizer = (settings, schema) => {
17096
      const namespaceTracker = createNamespaceTracker();
17097
      if (settings.sanitize) {
17098
        const purify = setupPurify(settings, schema, namespaceTracker);
17099
        const sanitizeHtmlElement = (body, mimeType) => {
17100
          purify.sanitize(body, getPurifyConfig(settings, mimeType));
17101
          purify.removed = [];
17102
          namespaceTracker.reset();
17103
        };
17104
        return {
17105
          sanitizeHtmlElement,
17106
          sanitizeNamespaceElement
17107
        };
17108
      } else {
17109
        const sanitizeHtmlElement = (body, _mimeType) => {
17110
          const nodeIterator = document.createNodeIterator(body, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT);
17111
          let node;
17112
          while (node = nodeIterator.nextNode()) {
17113
            const currentScope = namespaceTracker.track(node);
17114
            processNode(node, settings, schema, currentScope);
17115
            if (isElement$6(node)) {
17116
              filterAttributes(node, settings, schema, currentScope);
17117
            }
17118
          }
17119
          namespaceTracker.reset();
17120
        };
17121
        const sanitizeNamespaceElement = noop;
17122
        return {
17123
          sanitizeHtmlElement,
17124
          sanitizeNamespaceElement
17125
        };
17126
      }
17127
    };
17128
 
17129
    const makeMap = Tools.makeMap, extend$1 = Tools.extend;
17130
    const transferChildren = (parent, nativeParent, specialElements, nsSanitizer) => {
17131
      const parentName = parent.name;
17132
      const isSpecial = parentName in specialElements && parentName !== 'title' && parentName !== 'textarea';
17133
      const childNodes = nativeParent.childNodes;
17134
      for (let ni = 0, nl = childNodes.length; ni < nl; ni++) {
17135
        const nativeChild = childNodes[ni];
17136
        const child = new AstNode(nativeChild.nodeName.toLowerCase(), nativeChild.nodeType);
17137
        if (isElement$6(nativeChild)) {
17138
          const attributes = nativeChild.attributes;
17139
          for (let ai = 0, al = attributes.length; ai < al; ai++) {
17140
            const attr = attributes[ai];
17141
            child.attr(attr.name, attr.value);
17142
          }
17143
          if (isNonHtmlElementRootName(child.name)) {
17144
            nsSanitizer(nativeChild);
17145
            child.value = nativeChild.innerHTML;
17146
          }
17147
        } else if (isText$a(nativeChild)) {
17148
          child.value = nativeChild.data;
17149
          if (isSpecial) {
17150
            child.raw = true;
17151
          }
17152
        } else if (isComment(nativeChild) || isCData(nativeChild) || isPi(nativeChild)) {
17153
          child.value = nativeChild.data;
17154
        }
17155
        if (!isNonHtmlElementRootName(child.name)) {
17156
          transferChildren(child, nativeChild, specialElements, nsSanitizer);
17157
        }
17158
        parent.append(child);
17159
      }
17160
    };
17161
    const walkTree = (root, preprocessors, postprocessors) => {
17162
      const traverseOrder = [];
17163
      for (let node = root, lastNode = node; node; lastNode = node, node = node.walk()) {
17164
        const tempNode = node;
17165
        each$e(preprocessors, preprocess => preprocess(tempNode));
17166
        if (isNullable(tempNode.parent) && tempNode !== root) {
17167
          node = lastNode;
17168
        } else {
17169
          traverseOrder.push(tempNode);
17170
        }
17171
      }
17172
      for (let i = traverseOrder.length - 1; i >= 0; i--) {
17173
        const node = traverseOrder[i];
17174
        each$e(postprocessors, postprocess => postprocess(node));
17175
      }
17176
    };
17177
    const whitespaceCleaner = (root, schema, settings, args) => {
17178
      const validate = settings.validate;
17179
      const nonEmptyElements = schema.getNonEmptyElements();
17180
      const whitespaceElements = schema.getWhitespaceElements();
17181
      const blockElements = extend$1(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
17182
      const textRootBlockElements = getTextRootBlockElements(schema);
17183
      const allWhiteSpaceRegExp = /[ \t\r\n]+/g;
17184
      const startWhiteSpaceRegExp = /^[ \t\r\n]+/;
17185
      const endWhiteSpaceRegExp = /[ \t\r\n]+$/;
17186
      const hasWhitespaceParent = node => {
17187
        let tempNode = node.parent;
17188
        while (isNonNullable(tempNode)) {
17189
          if (tempNode.name in whitespaceElements) {
17190
            return true;
17191
          } else {
17192
            tempNode = tempNode.parent;
17193
          }
17194
        }
17195
        return false;
17196
      };
17197
      const isTextRootBlockEmpty = node => {
17198
        let tempNode = node;
17199
        while (isNonNullable(tempNode)) {
17200
          if (tempNode.name in textRootBlockElements) {
17201
            return isEmpty(schema, nonEmptyElements, whitespaceElements, tempNode);
17202
          } else {
17203
            tempNode = tempNode.parent;
17204
          }
17205
        }
17206
        return false;
17207
      };
17208
      const isBlock = node => node.name in blockElements || isTransparentAstBlock(schema, node) || isNonHtmlElementRootName(node.name) && node.parent === root;
17209
      const isAtEdgeOfBlock = (node, start) => {
17210
        const neighbour = start ? node.prev : node.next;
17211
        if (isNonNullable(neighbour) || isNullable(node.parent)) {
17212
          return false;
17213
        }
17214
        return isBlock(node.parent) && (node.parent !== root || args.isRootContent === true);
17215
      };
17216
      const preprocess = node => {
17217
        var _a;
17218
        if (node.type === 3) {
17219
          if (!hasWhitespaceParent(node)) {
17220
            let text = (_a = node.value) !== null && _a !== void 0 ? _a : '';
17221
            text = text.replace(allWhiteSpaceRegExp, ' ');
17222
            if (isLineBreakNode(node.prev, isBlock) || isAtEdgeOfBlock(node, true)) {
17223
              text = text.replace(startWhiteSpaceRegExp, '');
17224
            }
17225
            if (text.length === 0) {
17226
              node.remove();
17227
            } else {
17228
              node.value = text;
17229
            }
17230
          }
17231
        }
17232
      };
17233
      const postprocess = node => {
17234
        var _a;
17235
        if (node.type === 1) {
17236
          const elementRule = schema.getElementRule(node.name);
17237
          if (validate && elementRule) {
17238
            const isNodeEmpty = isEmpty(schema, nonEmptyElements, whitespaceElements, node);
17239
            if (elementRule.paddInEmptyBlock && isNodeEmpty && isTextRootBlockEmpty(node)) {
17240
              paddEmptyNode(settings, args, isBlock, node);
17241
            } else if (elementRule.removeEmpty && isNodeEmpty) {
17242
              if (isBlock(node)) {
17243
                node.remove();
17244
              } else {
17245
                node.unwrap();
17246
              }
17247
            } else if (elementRule.paddEmpty && (isNodeEmpty || isPaddedWithNbsp(node))) {
17248
              paddEmptyNode(settings, args, isBlock, node);
17249
            }
17250
          }
17251
        } else if (node.type === 3) {
17252
          if (!hasWhitespaceParent(node)) {
17253
            let text = (_a = node.value) !== null && _a !== void 0 ? _a : '';
17254
            if (node.next && isBlock(node.next) || isAtEdgeOfBlock(node, false)) {
17255
              text = text.replace(endWhiteSpaceRegExp, '');
17256
            }
17257
            if (text.length === 0) {
17258
              node.remove();
17259
            } else {
17260
              node.value = text;
17261
            }
17262
          }
17263
        }
17264
      };
17265
      return [
17266
        preprocess,
17267
        postprocess
17268
      ];
17269
    };
17270
    const getRootBlockName = (settings, args) => {
17271
      var _a;
17272
      const name = (_a = args.forced_root_block) !== null && _a !== void 0 ? _a : settings.forced_root_block;
17273
      if (name === false) {
17274
        return '';
17275
      } else if (name === true) {
17276
        return 'p';
17277
      } else {
17278
        return name;
17279
      }
17280
    };
17281
    const DomParser = (settings = {}, schema = Schema()) => {
17282
      const nodeFilterRegistry = create$8();
17283
      const attributeFilterRegistry = create$8();
17284
      const defaultedSettings = {
17285
        validate: true,
17286
        root_name: 'body',
17287
        sanitize: true,
17288
        ...settings
17289
      };
17290
      const parser = new DOMParser();
17291
      const sanitizer = getSanitizer(defaultedSettings, schema);
17292
      const parseAndSanitizeWithContext = (html, rootName, format = 'html') => {
17293
        const mimeType = format === 'xhtml' ? 'application/xhtml+xml' : 'text/html';
17294
        const isSpecialRoot = has$2(schema.getSpecialElements(), rootName.toLowerCase());
17295
        const content = isSpecialRoot ? `<${ rootName }>${ html }</${ rootName }>` : html;
17296
        const wrappedHtml = format === 'xhtml' ? `<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>${ content }</body></html>` : `<body>${ content }</body>`;
17297
        const body = parser.parseFromString(wrappedHtml, mimeType).body;
17298
        sanitizer.sanitizeHtmlElement(body, mimeType);
17299
        return isSpecialRoot ? body.firstChild : body;
17300
      };
17301
      const addNodeFilter = nodeFilterRegistry.addFilter;
17302
      const getNodeFilters = nodeFilterRegistry.getFilters;
17303
      const removeNodeFilter = nodeFilterRegistry.removeFilter;
17304
      const addAttributeFilter = attributeFilterRegistry.addFilter;
17305
      const getAttributeFilters = attributeFilterRegistry.getFilters;
17306
      const removeAttributeFilter = attributeFilterRegistry.removeFilter;
17307
      const findInvalidChildren = (node, invalidChildren) => {
17308
        if (isInvalid(schema, node)) {
17309
          invalidChildren.push(node);
17310
        }
17311
      };
17312
      const isWrappableNode = (blockElements, node) => {
17313
        const isInternalElement = isString(node.attr(internalElementAttr));
17314
        const isInlineElement = node.type === 1 && (!has$2(blockElements, node.name) && !isTransparentAstBlock(schema, node)) && !isNonHtmlElementRootName(node.name);
17315
        return node.type === 3 || isInlineElement && !isInternalElement;
17316
      };
17317
      const addRootBlocks = (rootNode, rootBlockName) => {
17318
        const blockElements = extend$1(makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements());
17319
        const startWhiteSpaceRegExp = /^[ \t\r\n]+/;
17320
        const endWhiteSpaceRegExp = /[ \t\r\n]+$/;
17321
        let node = rootNode.firstChild, rootBlockNode = null;
17322
        const trim = rootBlock => {
17323
          var _a, _b;
17324
          if (rootBlock) {
17325
            node = rootBlock.firstChild;
17326
            if (node && node.type === 3) {
17327
              node.value = (_a = node.value) === null || _a === void 0 ? void 0 : _a.replace(startWhiteSpaceRegExp, '');
17328
            }
17329
            node = rootBlock.lastChild;
17330
            if (node && node.type === 3) {
17331
              node.value = (_b = node.value) === null || _b === void 0 ? void 0 : _b.replace(endWhiteSpaceRegExp, '');
17332
            }
17333
          }
17334
        };
17335
        if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) {
17336
          return;
17337
        }
17338
        while (node) {
17339
          const next = node.next;
17340
          if (isWrappableNode(blockElements, node)) {
17341
            if (!rootBlockNode) {
17342
              rootBlockNode = new AstNode(rootBlockName, 1);
17343
              rootBlockNode.attr(defaultedSettings.forced_root_block_attrs);
17344
              rootNode.insert(rootBlockNode, node);
17345
              rootBlockNode.append(node);
17346
            } else {
17347
              rootBlockNode.append(node);
17348
            }
17349
          } else {
17350
            trim(rootBlockNode);
17351
            rootBlockNode = null;
17352
          }
17353
          node = next;
17354
        }
17355
        trim(rootBlockNode);
17356
      };
17357
      const parse = (html, args = {}) => {
17358
        var _a;
17359
        const validate = defaultedSettings.validate;
17360
        const rootName = (_a = args.context) !== null && _a !== void 0 ? _a : defaultedSettings.root_name;
17361
        const element = parseAndSanitizeWithContext(html, rootName, args.format);
17362
        updateChildren(schema, element);
17363
        const rootNode = new AstNode(rootName, 11);
17364
        transferChildren(rootNode, element, schema.getSpecialElements(), sanitizer.sanitizeNamespaceElement);
17365
        element.innerHTML = '';
17366
        const [whitespacePre, whitespacePost] = whitespaceCleaner(rootNode, schema, defaultedSettings, args);
17367
        const invalidChildren = [];
17368
        const invalidFinder = validate ? node => findInvalidChildren(node, invalidChildren) : noop;
17369
        const matches = {
17370
          nodes: {},
17371
          attributes: {}
17372
        };
17373
        const matchFinder = node => matchNode$1(getNodeFilters(), getAttributeFilters(), node, matches);
17374
        walkTree(rootNode, [
17375
          whitespacePre,
17376
          matchFinder
17377
        ], [
17378
          whitespacePost,
17379
          invalidFinder
17380
        ]);
17381
        invalidChildren.reverse();
17382
        if (validate && invalidChildren.length > 0) {
17383
          if (args.context) {
17384
            const {
17385
              pass: topLevelChildren,
17386
              fail: otherChildren
17387
            } = partition$2(invalidChildren, child => child.parent === rootNode);
17388
            cleanInvalidNodes(otherChildren, schema, rootNode, matchFinder);
17389
            args.invalid = topLevelChildren.length > 0;
17390
          } else {
17391
            cleanInvalidNodes(invalidChildren, schema, rootNode, matchFinder);
17392
          }
17393
        }
17394
        const rootBlockName = getRootBlockName(defaultedSettings, args);
17395
        if (rootBlockName && (rootNode.name === 'body' || args.isRootContent)) {
17396
          addRootBlocks(rootNode, rootBlockName);
17397
        }
17398
        if (!args.invalid) {
17399
          runFilters(matches, args);
17400
        }
17401
        return rootNode;
17402
      };
17403
      const exports = {
17404
        schema,
17405
        addAttributeFilter,
17406
        getAttributeFilters,
17407
        removeAttributeFilter,
17408
        addNodeFilter,
17409
        getNodeFilters,
17410
        removeNodeFilter,
17411
        parse
17412
      };
17413
      register$4(exports, defaultedSettings);
17414
      register$5(exports, defaultedSettings, schema);
17415
      return exports;
17416
    };
17417
 
17418
    const serializeContent = content => isTreeNode(content) ? HtmlSerializer({ validate: false }).serialize(content) : content;
17419
    const withSerializedContent = (content, fireEvent, parserSettings) => {
17420
      const serializedContent = serializeContent(content);
17421
      const eventArgs = fireEvent(serializedContent);
17422
      if (eventArgs.isDefaultPrevented()) {
17423
        return eventArgs;
17424
      } else if (isTreeNode(content)) {
17425
        if (eventArgs.content !== serializedContent) {
17426
          const rootNode = DomParser({
17427
            validate: false,
17428
            forced_root_block: false,
17429
            ...parserSettings
17430
          }).parse(eventArgs.content, { context: content.name });
17431
          return {
17432
            ...eventArgs,
17433
            content: rootNode
17434
          };
17435
        } else {
17436
          return {
17437
            ...eventArgs,
17438
            content
17439
          };
17440
        }
17441
      } else {
17442
        return eventArgs;
17443
      }
17444
    };
17445
    const preProcessGetContent = (editor, args) => {
17446
      if (args.no_events) {
17447
        return Result.value(args);
17448
      } else {
17449
        const eventArgs = fireBeforeGetContent(editor, args);
17450
        if (eventArgs.isDefaultPrevented()) {
17451
          return Result.error(fireGetContent(editor, {
17452
            content: '',
17453
            ...eventArgs
17454
          }).content);
17455
        } else {
17456
          return Result.value(eventArgs);
17457
        }
17458
      }
17459
    };
17460
    const postProcessGetContent = (editor, content, args) => {
17461
      if (args.no_events) {
17462
        return content;
17463
      } else {
17464
        const processedEventArgs = withSerializedContent(content, content => fireGetContent(editor, {
17465
          ...args,
17466
          content
17467
        }), {
17468
          sanitize: shouldSanitizeXss(editor),
17469
          sandbox_iframes: shouldSandboxIframes(editor)
17470
        });
17471
        return processedEventArgs.content;
17472
      }
17473
    };
17474
    const preProcessSetContent = (editor, args) => {
17475
      if (args.no_events) {
17476
        return Result.value(args);
17477
      } else {
17478
        const processedEventArgs = withSerializedContent(args.content, content => fireBeforeSetContent(editor, {
17479
          ...args,
17480
          content
17481
        }), {
17482
          sanitize: shouldSanitizeXss(editor),
17483
          sandbox_iframes: shouldSandboxIframes(editor)
17484
        });
17485
        if (processedEventArgs.isDefaultPrevented()) {
17486
          fireSetContent(editor, processedEventArgs);
17487
          return Result.error(undefined);
17488
        } else {
17489
          return Result.value(processedEventArgs);
17490
        }
17491
      }
17492
    };
17493
    const postProcessSetContent = (editor, content, args) => {
17494
      if (!args.no_events) {
17495
        fireSetContent(editor, {
17496
          ...args,
17497
          content
17498
        });
17499
      }
17500
    };
17501
 
17502
    const tableModel = (element, width, rows) => ({
17503
      element,
17504
      width,
17505
      rows
17506
    });
17507
    const tableRow = (element, cells) => ({
17508
      element,
17509
      cells
17510
    });
17511
    const cellPosition = (x, y) => ({
17512
      x,
17513
      y
17514
    });
17515
    const getSpan = (td, key) => {
17516
      return getOpt(td, key).bind(toInt).getOr(1);
17517
    };
17518
    const fillout = (table, x, y, tr, td) => {
17519
      const rowspan = getSpan(td, 'rowspan');
17520
      const colspan = getSpan(td, 'colspan');
17521
      const rows = table.rows;
17522
      for (let y2 = y; y2 < y + rowspan; y2++) {
17523
        if (!rows[y2]) {
17524
          rows[y2] = tableRow(deep$1(tr), []);
17525
        }
17526
        for (let x2 = x; x2 < x + colspan; x2++) {
17527
          const cells = rows[y2].cells;
17528
          cells[x2] = y2 === y && x2 === x ? td : shallow$1(td);
17529
        }
17530
      }
17531
    };
17532
    const cellExists = (table, x, y) => {
17533
      const rows = table.rows;
17534
      const cells = rows[y] ? rows[y].cells : [];
17535
      return !!cells[x];
17536
    };
17537
    const skipCellsX = (table, x, y) => {
17538
      while (cellExists(table, x, y)) {
17539
        x++;
17540
      }
17541
      return x;
17542
    };
17543
    const getWidth = rows => {
17544
      return foldl(rows, (acc, row) => {
17545
        return row.cells.length > acc ? row.cells.length : acc;
17546
      }, 0);
17547
    };
17548
    const findElementPos = (table, element) => {
17549
      const rows = table.rows;
17550
      for (let y = 0; y < rows.length; y++) {
17551
        const cells = rows[y].cells;
17552
        for (let x = 0; x < cells.length; x++) {
17553
          if (eq(cells[x], element)) {
17554
            return Optional.some(cellPosition(x, y));
17555
          }
17556
        }
17557
      }
17558
      return Optional.none();
17559
    };
17560
    const extractRows = (table, sx, sy, ex, ey) => {
17561
      const newRows = [];
17562
      const rows = table.rows;
17563
      for (let y = sy; y <= ey; y++) {
17564
        const cells = rows[y].cells;
17565
        const slice = sx < ex ? cells.slice(sx, ex + 1) : cells.slice(ex, sx + 1);
17566
        newRows.push(tableRow(rows[y].element, slice));
17567
      }
17568
      return newRows;
17569
    };
17570
    const subTable = (table, startPos, endPos) => {
17571
      const sx = startPos.x, sy = startPos.y;
17572
      const ex = endPos.x, ey = endPos.y;
17573
      const newRows = sy < ey ? extractRows(table, sx, sy, ex, ey) : extractRows(table, sx, ey, ex, sy);
17574
      return tableModel(table.element, getWidth(newRows), newRows);
17575
    };
17576
    const createDomTable = (table, rows) => {
17577
      const tableElement = shallow$1(table.element);
17578
      const tableBody = SugarElement.fromTag('tbody');
17579
      append(tableBody, rows);
17580
      append$1(tableElement, tableBody);
17581
      return tableElement;
17582
    };
17583
    const modelRowsToDomRows = table => {
17584
      return map$3(table.rows, row => {
17585
        const cells = map$3(row.cells, cell => {
17586
          const td = deep$1(cell);
17587
          remove$a(td, 'colspan');
17588
          remove$a(td, 'rowspan');
17589
          return td;
17590
        });
17591
        const tr = shallow$1(row.element);
17592
        append(tr, cells);
17593
        return tr;
17594
      });
17595
    };
17596
    const fromDom = tableElm => {
17597
      const table = tableModel(shallow$1(tableElm), 0, []);
17598
      each$e(descendants(tableElm, 'tr'), (tr, y) => {
17599
        each$e(descendants(tr, 'td,th'), (td, x) => {
17600
          fillout(table, skipCellsX(table, x, y), y, tr, td);
17601
        });
17602
      });
17603
      return tableModel(table.element, getWidth(table.rows), table.rows);
17604
    };
17605
    const toDom = table => {
17606
      return createDomTable(table, modelRowsToDomRows(table));
17607
    };
17608
    const subsection = (table, startElement, endElement) => {
17609
      return findElementPos(table, startElement).bind(startPos => {
17610
        return findElementPos(table, endElement).map(endPos => {
17611
          return subTable(table, startPos, endPos);
17612
        });
17613
      });
17614
    };
17615
 
17616
    const findParentListContainer = parents => find$2(parents, elm => name(elm) === 'ul' || name(elm) === 'ol');
17617
    const getFullySelectedListWrappers = (parents, rng) => find$2(parents, elm => name(elm) === 'li' && hasAllContentsSelected(elm, rng)).fold(constant([]), _li => findParentListContainer(parents).map(listCont => {
17618
      const listElm = SugarElement.fromTag(name(listCont));
17619
      const listStyles = filter$4(getAllRaw(listCont), (_style, name) => startsWith(name, 'list-style'));
17620
      setAll(listElm, listStyles);
17621
      return [
17622
        SugarElement.fromTag('li'),
17623
        listElm
17624
      ];
17625
    }).getOr([]));
17626
    const wrap = (innerElm, elms) => {
17627
      const wrapped = foldl(elms, (acc, elm) => {
17628
        append$1(elm, acc);
17629
        return elm;
17630
      }, innerElm);
17631
      return elms.length > 0 ? fromElements([wrapped]) : wrapped;
17632
    };
17633
    const directListWrappers = commonAnchorContainer => {
17634
      if (isListItem$1(commonAnchorContainer)) {
17635
        return parent(commonAnchorContainer).filter(isList).fold(constant([]), listElm => [
17636
          commonAnchorContainer,
17637
          listElm
17638
        ]);
17639
      } else {
17640
        return isList(commonAnchorContainer) ? [commonAnchorContainer] : [];
17641
      }
17642
    };
17643
    const getWrapElements = (rootNode, rng, schema) => {
17644
      const commonAnchorContainer = SugarElement.fromDom(rng.commonAncestorContainer);
17645
      const parents = parentsAndSelf(commonAnchorContainer, rootNode);
17646
      const wrapElements = filter$5(parents, el => schema.isWrapper(name(el)));
17647
      const listWrappers = getFullySelectedListWrappers(parents, rng);
17648
      const allWrappers = wrapElements.concat(listWrappers.length ? listWrappers : directListWrappers(commonAnchorContainer));
17649
      return map$3(allWrappers, shallow$1);
17650
    };
17651
    const emptyFragment = () => fromElements([]);
17652
    const getFragmentFromRange = (rootNode, rng, schema) => wrap(SugarElement.fromDom(rng.cloneContents()), getWrapElements(rootNode, rng, schema));
17653
    const getParentTable = (rootElm, cell) => ancestor$3(cell, 'table', curry(eq, rootElm));
17654
    const getTableFragment = (rootNode, selectedTableCells) => getParentTable(rootNode, selectedTableCells[0]).bind(tableElm => {
17655
      const firstCell = selectedTableCells[0];
17656
      const lastCell = selectedTableCells[selectedTableCells.length - 1];
17657
      const fullTableModel = fromDom(tableElm);
17658
      return subsection(fullTableModel, firstCell, lastCell).map(sectionedTableModel => fromElements([toDom(sectionedTableModel)]));
17659
    }).getOrThunk(emptyFragment);
17660
    const getSelectionFragment = (rootNode, ranges, schema) => ranges.length > 0 && ranges[0].collapsed ? emptyFragment() : getFragmentFromRange(rootNode, ranges[0], schema);
17661
    const read$3 = (rootNode, ranges, schema) => {
17662
      const selectedCells = getCellsFromElementOrRanges(ranges, rootNode);
17663
      return selectedCells.length > 0 ? getTableFragment(rootNode, selectedCells) : getSelectionFragment(rootNode, ranges, schema);
17664
    };
17665
 
17666
    const isCollapsibleWhitespace = (text, index) => index >= 0 && index < text.length && isWhiteSpace(text.charAt(index));
17667
    const getInnerText = bin => {
17668
      return trim$2(bin.innerText);
17669
    };
17670
    const getContextNodeName = parentBlockOpt => parentBlockOpt.map(block => block.nodeName).getOr('div').toLowerCase();
17671
    const getTextContent = editor => Optional.from(editor.selection.getRng()).map(rng => {
17672
      var _a;
17673
      const parentBlockOpt = Optional.from(editor.dom.getParent(rng.commonAncestorContainer, editor.dom.isBlock));
17674
      const body = editor.getBody();
17675
      const contextNodeName = getContextNodeName(parentBlockOpt);
17676
      const rangeContentClone = SugarElement.fromDom(rng.cloneContents());
17677
      cleanupBogusElements(rangeContentClone);
17678
      cleanupInputNames(rangeContentClone);
17679
      const bin = editor.dom.add(body, contextNodeName, {
17680
        'data-mce-bogus': 'all',
17681
        'style': 'overflow: hidden; opacity: 0;'
17682
      }, rangeContentClone.dom);
17683
      const text = getInnerText(bin);
17684
      const nonRenderedText = trim$2((_a = bin.textContent) !== null && _a !== void 0 ? _a : '');
17685
      editor.dom.remove(bin);
17686
      if (isCollapsibleWhitespace(nonRenderedText, 0) || isCollapsibleWhitespace(nonRenderedText, nonRenderedText.length - 1)) {
17687
        const parentBlock = parentBlockOpt.getOr(body);
17688
        const parentBlockText = getInnerText(parentBlock);
17689
        const textIndex = parentBlockText.indexOf(text);
17690
        if (textIndex === -1) {
17691
          return text;
17692
        } else {
17693
          const hasProceedingSpace = isCollapsibleWhitespace(parentBlockText, textIndex - 1);
17694
          const hasTrailingSpace = isCollapsibleWhitespace(parentBlockText, textIndex + text.length);
17695
          return (hasProceedingSpace ? ' ' : '') + text + (hasTrailingSpace ? ' ' : '');
17696
        }
17697
      } else {
17698
        return text;
17699
      }
17700
    }).getOr('');
17701
    const getSerializedContent = (editor, args) => {
17702
      const rng = editor.selection.getRng(), tmpElm = editor.dom.create('body');
17703
      const sel = editor.selection.getSel();
17704
      const ranges = processRanges(editor, getRanges$1(sel));
17705
      const fragment = args.contextual ? read$3(SugarElement.fromDom(editor.getBody()), ranges, editor.schema).dom : rng.cloneContents();
17706
      if (fragment) {
17707
        tmpElm.appendChild(fragment);
17708
      }
17709
      return editor.selection.serializer.serialize(tmpElm, args);
17710
    };
17711
    const extractSelectedContent = (editor, args) => {
17712
      if (args.format === 'text') {
17713
        return getTextContent(editor);
17714
      } else {
17715
        const content = getSerializedContent(editor, args);
17716
        if (args.format === 'tree') {
17717
          return content;
17718
        } else {
17719
          return editor.selection.isCollapsed() ? '' : content;
17720
        }
17721
      }
17722
    };
17723
    const setupArgs$3 = (args, format) => ({
17724
      ...args,
17725
      format,
17726
      get: true,
17727
      selection: true,
17728
      getInner: true
17729
    });
17730
    const getSelectedContentInternal = (editor, format, args = {}) => {
17731
      const defaultedArgs = setupArgs$3(args, format);
17732
      return preProcessGetContent(editor, defaultedArgs).fold(identity, updatedArgs => {
17733
        const content = extractSelectedContent(editor, updatedArgs);
17734
        return postProcessGetContent(editor, content, updatedArgs);
17735
      });
17736
    };
17737
 
17738
    const KEEP = 0, INSERT = 1, DELETE = 2;
17739
    const diff = (left, right) => {
17740
      const size = left.length + right.length + 2;
17741
      const vDown = new Array(size);
17742
      const vUp = new Array(size);
17743
      const snake = (start, end, diag) => {
17744
        return {
17745
          start,
17746
          end,
17747
          diag
17748
        };
17749
      };
17750
      const buildScript = (start1, end1, start2, end2, script) => {
17751
        const middle = getMiddleSnake(start1, end1, start2, end2);
17752
        if (middle === null || middle.start === end1 && middle.diag === end1 - end2 || middle.end === start1 && middle.diag === start1 - start2) {
17753
          let i = start1;
17754
          let j = start2;
17755
          while (i < end1 || j < end2) {
17756
            if (i < end1 && j < end2 && left[i] === right[j]) {
17757
              script.push([
17758
                KEEP,
17759
                left[i]
17760
              ]);
17761
              ++i;
17762
              ++j;
17763
            } else {
17764
              if (end1 - start1 > end2 - start2) {
17765
                script.push([
17766
                  DELETE,
17767
                  left[i]
17768
                ]);
17769
                ++i;
17770
              } else {
17771
                script.push([
17772
                  INSERT,
17773
                  right[j]
17774
                ]);
17775
                ++j;
17776
              }
17777
            }
17778
          }
17779
        } else {
17780
          buildScript(start1, middle.start, start2, middle.start - middle.diag, script);
17781
          for (let i2 = middle.start; i2 < middle.end; ++i2) {
17782
            script.push([
17783
              KEEP,
17784
              left[i2]
17785
            ]);
17786
          }
17787
          buildScript(middle.end, end1, middle.end - middle.diag, end2, script);
17788
        }
17789
      };
17790
      const buildSnake = (start, diag, end1, end2) => {
17791
        let end = start;
17792
        while (end - diag < end2 && end < end1 && left[end] === right[end - diag]) {
17793
          ++end;
17794
        }
17795
        return snake(start, end, diag);
17796
      };
17797
      const getMiddleSnake = (start1, end1, start2, end2) => {
17798
        const m = end1 - start1;
17799
        const n = end2 - start2;
17800
        if (m === 0 || n === 0) {
17801
          return null;
17802
        }
17803
        const delta = m - n;
17804
        const sum = n + m;
17805
        const offset = (sum % 2 === 0 ? sum : sum + 1) / 2;
17806
        vDown[1 + offset] = start1;
17807
        vUp[1 + offset] = end1 + 1;
17808
        let d, k, i, x, y;
17809
        for (d = 0; d <= offset; ++d) {
17810
          for (k = -d; k <= d; k += 2) {
17811
            i = k + offset;
17812
            if (k === -d || k !== d && vDown[i - 1] < vDown[i + 1]) {
17813
              vDown[i] = vDown[i + 1];
17814
            } else {
17815
              vDown[i] = vDown[i - 1] + 1;
17816
            }
17817
            x = vDown[i];
17818
            y = x - start1 + start2 - k;
17819
            while (x < end1 && y < end2 && left[x] === right[y]) {
17820
              vDown[i] = ++x;
17821
              ++y;
17822
            }
17823
            if (delta % 2 !== 0 && delta - d <= k && k <= delta + d) {
17824
              if (vUp[i - delta] <= vDown[i]) {
17825
                return buildSnake(vUp[i - delta], k + start1 - start2, end1, end2);
17826
              }
17827
            }
17828
          }
17829
          for (k = delta - d; k <= delta + d; k += 2) {
17830
            i = k + offset - delta;
17831
            if (k === delta - d || k !== delta + d && vUp[i + 1] <= vUp[i - 1]) {
17832
              vUp[i] = vUp[i + 1] - 1;
17833
            } else {
17834
              vUp[i] = vUp[i - 1];
17835
            }
17836
            x = vUp[i] - 1;
17837
            y = x - start1 + start2 - k;
17838
            while (x >= start1 && y >= start2 && left[x] === right[y]) {
17839
              vUp[i] = x--;
17840
              y--;
17841
            }
17842
            if (delta % 2 === 0 && -d <= k && k <= d) {
17843
              if (vUp[i] <= vDown[i + delta]) {
17844
                return buildSnake(vUp[i], k + start1 - start2, end1, end2);
17845
              }
17846
            }
17847
          }
17848
        }
17849
        return null;
17850
      };
17851
      const script = [];
17852
      buildScript(0, left.length, 0, right.length, script);
17853
      return script;
17854
    };
17855
 
17856
    const getOuterHtml = elm => {
17857
      if (isElement$6(elm)) {
17858
        return elm.outerHTML;
17859
      } else if (isText$a(elm)) {
17860
        return Entities.encodeRaw(elm.data, false);
17861
      } else if (isComment(elm)) {
17862
        return '<!--' + elm.data + '-->';
17863
      }
17864
      return '';
17865
    };
17866
    const createFragment = html => {
17867
      let node;
17868
      const container = document.createElement('div');
17869
      const frag = document.createDocumentFragment();
17870
      if (html) {
17871
        container.innerHTML = html;
17872
      }
17873
      while (node = container.firstChild) {
17874
        frag.appendChild(node);
17875
      }
17876
      return frag;
17877
    };
17878
    const insertAt = (elm, html, index) => {
17879
      const fragment = createFragment(html);
17880
      if (elm.hasChildNodes() && index < elm.childNodes.length) {
17881
        const target = elm.childNodes[index];
17882
        elm.insertBefore(fragment, target);
17883
      } else {
17884
        elm.appendChild(fragment);
17885
      }
17886
    };
17887
    const removeAt = (elm, index) => {
17888
      if (elm.hasChildNodes() && index < elm.childNodes.length) {
17889
        const target = elm.childNodes[index];
17890
        elm.removeChild(target);
17891
      }
17892
    };
17893
    const applyDiff = (diff, elm) => {
17894
      let index = 0;
17895
      each$e(diff, action => {
17896
        if (action[0] === KEEP) {
17897
          index++;
17898
        } else if (action[0] === INSERT) {
17899
          insertAt(elm, action[1], index);
17900
          index++;
17901
        } else if (action[0] === DELETE) {
17902
          removeAt(elm, index);
17903
        }
17904
      });
17905
    };
17906
    const read$2 = (elm, trimZwsp) => filter$5(map$3(from(elm.childNodes), trimZwsp ? compose(trim$2, getOuterHtml) : getOuterHtml), item => {
17907
      return item.length > 0;
17908
    });
17909
    const write = (fragments, elm) => {
17910
      const currentFragments = map$3(from(elm.childNodes), getOuterHtml);
17911
      applyDiff(diff(currentFragments, fragments), elm);
17912
      return elm;
17913
    };
17914
 
17915
    const lazyTempDocument = cached(() => document.implementation.createHTMLDocument('undo'));
17916
    const hasIframes = body => body.querySelector('iframe') !== null;
17917
    const createFragmentedLevel = fragments => {
17918
      return {
17919
        type: 'fragmented',
17920
        fragments,
17921
        content: '',
17922
        bookmark: null,
17923
        beforeBookmark: null
17924
      };
17925
    };
17926
    const createCompleteLevel = content => {
17927
      return {
17928
        type: 'complete',
17929
        fragments: null,
17930
        content,
17931
        bookmark: null,
17932
        beforeBookmark: null
17933
      };
17934
    };
17935
    const createFromEditor = editor => {
17936
      const tempAttrs = editor.serializer.getTempAttrs();
17937
      const body = trim$1(editor.getBody(), tempAttrs);
17938
      return hasIframes(body) ? createFragmentedLevel(read$2(body, true)) : createCompleteLevel(trim$2(body.innerHTML));
17939
    };
17940
    const applyToEditor = (editor, level, before) => {
17941
      const bookmark = before ? level.beforeBookmark : level.bookmark;
17942
      if (level.type === 'fragmented') {
17943
        write(level.fragments, editor.getBody());
17944
      } else {
17945
        editor.setContent(level.content, {
17946
          format: 'raw',
17947
          no_selection: isNonNullable(bookmark) && isPathBookmark(bookmark) ? !bookmark.isFakeCaret : true
17948
        });
17949
      }
17950
      if (bookmark) {
17951
        editor.selection.moveToBookmark(bookmark);
17952
        editor.selection.scrollIntoView();
17953
      }
17954
    };
17955
    const getLevelContent = level => {
17956
      return level.type === 'fragmented' ? level.fragments.join('') : level.content;
17957
    };
17958
    const getCleanLevelContent = level => {
17959
      const elm = SugarElement.fromTag('body', lazyTempDocument());
17960
      set$1(elm, getLevelContent(level));
17961
      each$e(descendants(elm, '*[data-mce-bogus]'), unwrap);
17962
      return get$6(elm);
17963
    };
17964
    const hasEqualContent = (level1, level2) => getLevelContent(level1) === getLevelContent(level2);
17965
    const hasEqualCleanedContent = (level1, level2) => getCleanLevelContent(level1) === getCleanLevelContent(level2);
17966
    const isEq$1 = (level1, level2) => {
17967
      if (!level1 || !level2) {
17968
        return false;
17969
      } else if (hasEqualContent(level1, level2)) {
17970
        return true;
17971
      } else {
17972
        return hasEqualCleanedContent(level1, level2);
17973
      }
17974
    };
17975
 
17976
    const isUnlocked = locks => locks.get() === 0;
17977
 
17978
    const setTyping = (undoManager, typing, locks) => {
17979
      if (isUnlocked(locks)) {
17980
        undoManager.typing = typing;
17981
      }
17982
    };
17983
    const endTyping = (undoManager, locks) => {
17984
      if (undoManager.typing) {
17985
        setTyping(undoManager, false, locks);
17986
        undoManager.add();
17987
      }
17988
    };
17989
    const endTypingLevelIgnoreLocks = undoManager => {
17990
      if (undoManager.typing) {
17991
        undoManager.typing = false;
17992
        undoManager.add();
17993
      }
17994
    };
17995
 
17996
    const beforeChange$1 = (editor, locks, beforeBookmark) => {
17997
      if (isUnlocked(locks)) {
17998
        beforeBookmark.set(getUndoBookmark(editor.selection));
17999
      }
18000
    };
18001
    const addUndoLevel$1 = (editor, undoManager, index, locks, beforeBookmark, level, event) => {
18002
      const currentLevel = createFromEditor(editor);
18003
      const newLevel = Tools.extend(level || {}, currentLevel);
18004
      if (!isUnlocked(locks) || editor.removed) {
18005
        return null;
18006
      }
18007
      const lastLevel = undoManager.data[index.get()];
18008
      if (editor.dispatch('BeforeAddUndo', {
18009
          level: newLevel,
18010
          lastLevel,
18011
          originalEvent: event
18012
        }).isDefaultPrevented()) {
18013
        return null;
18014
      }
18015
      if (lastLevel && isEq$1(lastLevel, newLevel)) {
18016
        return null;
18017
      }
18018
      if (undoManager.data[index.get()]) {
18019
        beforeBookmark.get().each(bm => {
18020
          undoManager.data[index.get()].beforeBookmark = bm;
18021
        });
18022
      }
18023
      const customUndoRedoLevels = getCustomUndoRedoLevels(editor);
18024
      if (customUndoRedoLevels) {
18025
        if (undoManager.data.length > customUndoRedoLevels) {
18026
          for (let i = 0; i < undoManager.data.length - 1; i++) {
18027
            undoManager.data[i] = undoManager.data[i + 1];
18028
          }
18029
          undoManager.data.length--;
18030
          index.set(undoManager.data.length);
18031
        }
18032
      }
18033
      newLevel.bookmark = getUndoBookmark(editor.selection);
18034
      if (index.get() < undoManager.data.length - 1) {
18035
        undoManager.data.length = index.get() + 1;
18036
      }
18037
      undoManager.data.push(newLevel);
18038
      index.set(undoManager.data.length - 1);
18039
      const args = {
18040
        level: newLevel,
18041
        lastLevel,
18042
        originalEvent: event
18043
      };
18044
      if (index.get() > 0) {
18045
        editor.setDirty(true);
18046
        editor.dispatch('AddUndo', args);
18047
        editor.dispatch('change', args);
18048
      } else {
18049
        editor.dispatch('AddUndo', args);
18050
      }
18051
      return newLevel;
18052
    };
18053
    const clear$1 = (editor, undoManager, index) => {
18054
      undoManager.data = [];
18055
      index.set(0);
18056
      undoManager.typing = false;
18057
      editor.dispatch('ClearUndos');
18058
    };
18059
    const extra$1 = (editor, undoManager, index, callback1, callback2) => {
18060
      if (undoManager.transact(callback1)) {
18061
        const bookmark = undoManager.data[index.get()].bookmark;
18062
        const lastLevel = undoManager.data[index.get() - 1];
18063
        applyToEditor(editor, lastLevel, true);
18064
        if (undoManager.transact(callback2)) {
18065
          undoManager.data[index.get() - 1].beforeBookmark = bookmark;
18066
        }
18067
      }
18068
    };
18069
    const redo$1 = (editor, index, data) => {
18070
      let level;
18071
      if (index.get() < data.length - 1) {
18072
        index.set(index.get() + 1);
18073
        level = data[index.get()];
18074
        applyToEditor(editor, level, false);
18075
        editor.setDirty(true);
18076
        editor.dispatch('Redo', { level });
18077
      }
18078
      return level;
18079
    };
18080
    const undo$1 = (editor, undoManager, locks, index) => {
18081
      let level;
18082
      if (undoManager.typing) {
18083
        undoManager.add();
18084
        undoManager.typing = false;
18085
        setTyping(undoManager, false, locks);
18086
      }
18087
      if (index.get() > 0) {
18088
        index.set(index.get() - 1);
18089
        level = undoManager.data[index.get()];
18090
        applyToEditor(editor, level, true);
18091
        editor.setDirty(true);
18092
        editor.dispatch('Undo', { level });
18093
      }
18094
      return level;
18095
    };
18096
    const reset$1 = undoManager => {
18097
      undoManager.clear();
18098
      undoManager.add();
18099
    };
18100
    const hasUndo$1 = (editor, undoManager, index) => index.get() > 0 || undoManager.typing && undoManager.data[0] && !isEq$1(createFromEditor(editor), undoManager.data[0]);
18101
    const hasRedo$1 = (undoManager, index) => index.get() < undoManager.data.length - 1 && !undoManager.typing;
18102
    const transact$1 = (undoManager, locks, callback) => {
18103
      endTyping(undoManager, locks);
18104
      undoManager.beforeChange();
18105
      undoManager.ignore(callback);
18106
      return undoManager.add();
18107
    };
18108
    const ignore$1 = (locks, callback) => {
18109
      try {
18110
        locks.set(locks.get() + 1);
18111
        callback();
18112
      } finally {
18113
        locks.set(locks.get() - 1);
18114
      }
18115
    };
18116
 
18117
    const addVisualInternal = (editor, elm) => {
18118
      const dom = editor.dom;
18119
      const scope = isNonNullable(elm) ? elm : editor.getBody();
18120
      each$e(dom.select('table,a', scope), matchedElm => {
18121
        switch (matchedElm.nodeName) {
18122
        case 'TABLE':
18123
          const cls = getVisualAidsTableClass(editor);
18124
          const value = dom.getAttrib(matchedElm, 'border');
18125
          if ((!value || value === '0') && editor.hasVisual) {
18126
            dom.addClass(matchedElm, cls);
18127
          } else {
18128
            dom.removeClass(matchedElm, cls);
18129
          }
18130
          break;
18131
        case 'A':
18132
          if (!dom.getAttrib(matchedElm, 'href')) {
18133
            const value = dom.getAttrib(matchedElm, 'name') || matchedElm.id;
18134
            const cls = getVisualAidsAnchorClass(editor);
18135
            if (value && editor.hasVisual) {
18136
              dom.addClass(matchedElm, cls);
18137
            } else {
18138
              dom.removeClass(matchedElm, cls);
18139
            }
18140
          }
18141
          break;
18142
        }
18143
      });
18144
      editor.dispatch('VisualAid', {
18145
        element: elm,
18146
        hasVisual: editor.hasVisual
18147
      });
18148
    };
18149
 
18150
    const makePlainAdaptor = editor => ({
18151
      init: { bindEvents: noop },
18152
      undoManager: {
18153
        beforeChange: (locks, beforeBookmark) => beforeChange$1(editor, locks, beforeBookmark),
18154
        add: (undoManager, index, locks, beforeBookmark, level, event) => addUndoLevel$1(editor, undoManager, index, locks, beforeBookmark, level, event),
18155
        undo: (undoManager, locks, index) => undo$1(editor, undoManager, locks, index),
18156
        redo: (index, data) => redo$1(editor, index, data),
18157
        clear: (undoManager, index) => clear$1(editor, undoManager, index),
18158
        reset: undoManager => reset$1(undoManager),
18159
        hasUndo: (undoManager, index) => hasUndo$1(editor, undoManager, index),
18160
        hasRedo: (undoManager, index) => hasRedo$1(undoManager, index),
18161
        transact: (undoManager, locks, callback) => transact$1(undoManager, locks, callback),
18162
        ignore: (locks, callback) => ignore$1(locks, callback),
18163
        extra: (undoManager, index, callback1, callback2) => extra$1(editor, undoManager, index, callback1, callback2)
18164
      },
18165
      formatter: {
18166
        match: (name, vars, node, similar) => match$2(editor, name, vars, node, similar),
18167
        matchAll: (names, vars) => matchAll(editor, names, vars),
18168
        matchNode: (node, name, vars, similar) => matchNode(editor, node, name, vars, similar),
18169
        canApply: name => canApply(editor, name),
18170
        closest: names => closest(editor, names),
18171
        apply: (name, vars, node) => applyFormat$1(editor, name, vars, node),
18172
        remove: (name, vars, node, similar) => removeFormat$1(editor, name, vars, node, similar),
18173
        toggle: (name, vars, node) => toggle(editor, name, vars, node),
18174
        formatChanged: (registeredFormatListeners, formats, callback, similar, vars) => formatChangedInternal(editor, registeredFormatListeners, formats, callback, similar, vars)
18175
      },
18176
      editor: {
18177
        getContent: args => getContentInternal(editor, args),
18178
        setContent: (content, args) => setContentInternal(editor, content, args),
18179
        insertContent: (value, details) => insertHtmlAtCaret(editor, value, details),
18180
        addVisual: elm => addVisualInternal(editor, elm)
18181
      },
18182
      selection: { getContent: (format, args) => getSelectedContentInternal(editor, format, args) },
18183
      autocompleter: {
18184
        addDecoration: range => create$9(editor, range),
18185
        removeDecoration: () => remove$2(editor, SugarElement.fromDom(editor.getBody()))
18186
      },
18187
      raw: { getModel: () => Optional.none() }
18188
    });
18189
    const makeRtcAdaptor = rtcEditor => {
18190
      const defaultVars = vars => isObject(vars) ? vars : {};
18191
      const {init, undoManager, formatter, editor, selection, autocompleter, raw} = rtcEditor;
18192
      return {
18193
        init: { bindEvents: init.bindEvents },
18194
        undoManager: {
18195
          beforeChange: undoManager.beforeChange,
18196
          add: undoManager.add,
18197
          undo: undoManager.undo,
18198
          redo: undoManager.redo,
18199
          clear: undoManager.clear,
18200
          reset: undoManager.reset,
18201
          hasUndo: undoManager.hasUndo,
18202
          hasRedo: undoManager.hasRedo,
18203
          transact: (_undoManager, _locks, fn) => undoManager.transact(fn),
18204
          ignore: (_locks, callback) => undoManager.ignore(callback),
18205
          extra: (_undoManager, _index, callback1, callback2) => undoManager.extra(callback1, callback2)
18206
        },
18207
        formatter: {
18208
          match: (name, vars, _node, similar) => formatter.match(name, defaultVars(vars), similar),
18209
          matchAll: formatter.matchAll,
18210
          matchNode: formatter.matchNode,
18211
          canApply: name => formatter.canApply(name),
18212
          closest: names => formatter.closest(names),
18213
          apply: (name, vars, _node) => formatter.apply(name, defaultVars(vars)),
18214
          remove: (name, vars, _node, _similar) => formatter.remove(name, defaultVars(vars)),
18215
          toggle: (name, vars, _node) => formatter.toggle(name, defaultVars(vars)),
18216
          formatChanged: (_rfl, formats, callback, similar, vars) => formatter.formatChanged(formats, callback, similar, vars)
18217
        },
18218
        editor: {
18219
          getContent: args => editor.getContent(args),
18220
          setContent: (content, args) => {
18221
            return {
18222
              content: editor.setContent(content, args),
18223
              html: ''
18224
            };
18225
          },
18226
          insertContent: (content, _details) => {
18227
            editor.insertContent(content);
18228
            return '';
18229
          },
18230
          addVisual: editor.addVisual
18231
        },
18232
        selection: { getContent: (_format, args) => selection.getContent(args) },
18233
        autocompleter: {
18234
          addDecoration: autocompleter.addDecoration,
18235
          removeDecoration: autocompleter.removeDecoration
18236
        },
18237
        raw: { getModel: () => Optional.some(raw.getRawModel()) }
18238
      };
18239
    };
18240
    const makeNoopAdaptor = () => {
18241
      const nul = constant(null);
18242
      const empty = constant('');
18243
      return {
18244
        init: { bindEvents: noop },
18245
        undoManager: {
18246
          beforeChange: noop,
18247
          add: nul,
18248
          undo: nul,
18249
          redo: nul,
18250
          clear: noop,
18251
          reset: noop,
18252
          hasUndo: never,
18253
          hasRedo: never,
18254
          transact: nul,
18255
          ignore: noop,
18256
          extra: noop
18257
        },
18258
        formatter: {
18259
          match: never,
18260
          matchAll: constant([]),
18261
          matchNode: constant(undefined),
18262
          canApply: never,
18263
          closest: empty,
18264
          apply: noop,
18265
          remove: noop,
18266
          toggle: noop,
18267
          formatChanged: constant({ unbind: noop })
18268
        },
18269
        editor: {
18270
          getContent: empty,
18271
          setContent: constant({
18272
            content: '',
18273
            html: ''
18274
          }),
18275
          insertContent: constant(''),
18276
          addVisual: noop
18277
        },
18278
        selection: { getContent: empty },
18279
        autocompleter: {
18280
          addDecoration: noop,
18281
          removeDecoration: noop
18282
        },
18283
        raw: { getModel: constant(Optional.none()) }
18284
      };
18285
    };
18286
    const isRtc = editor => has$2(editor.plugins, 'rtc');
18287
    const getRtcSetup = editor => get$a(editor.plugins, 'rtc').bind(rtcPlugin => Optional.from(rtcPlugin.setup));
18288
    const setup$t = editor => {
18289
      const editorCast = editor;
18290
      return getRtcSetup(editor).fold(() => {
18291
        editorCast.rtcInstance = makePlainAdaptor(editor);
18292
        return Optional.none();
18293
      }, setup => {
18294
        editorCast.rtcInstance = makeNoopAdaptor();
18295
        return Optional.some(() => setup().then(rtcEditor => {
18296
          editorCast.rtcInstance = makeRtcAdaptor(rtcEditor);
18297
          return rtcEditor.rtc.isRemote;
18298
        }));
18299
      });
18300
    };
18301
    const getRtcInstanceWithFallback = editor => editor.rtcInstance ? editor.rtcInstance : makePlainAdaptor(editor);
18302
    const getRtcInstanceWithError = editor => {
18303
      const rtcInstance = editor.rtcInstance;
18304
      if (!rtcInstance) {
18305
        throw new Error('Failed to get RTC instance not yet initialized.');
18306
      } else {
18307
        return rtcInstance;
18308
      }
18309
    };
18310
    const beforeChange = (editor, locks, beforeBookmark) => {
18311
      getRtcInstanceWithError(editor).undoManager.beforeChange(locks, beforeBookmark);
18312
    };
18313
    const addUndoLevel = (editor, undoManager, index, locks, beforeBookmark, level, event) => getRtcInstanceWithError(editor).undoManager.add(undoManager, index, locks, beforeBookmark, level, event);
18314
    const undo = (editor, undoManager, locks, index) => getRtcInstanceWithError(editor).undoManager.undo(undoManager, locks, index);
18315
    const redo = (editor, index, data) => getRtcInstanceWithError(editor).undoManager.redo(index, data);
18316
    const clear = (editor, undoManager, index) => {
18317
      getRtcInstanceWithError(editor).undoManager.clear(undoManager, index);
18318
    };
18319
    const reset = (editor, undoManager) => {
18320
      getRtcInstanceWithError(editor).undoManager.reset(undoManager);
18321
    };
18322
    const hasUndo = (editor, undoManager, index) => getRtcInstanceWithError(editor).undoManager.hasUndo(undoManager, index);
18323
    const hasRedo = (editor, undoManager, index) => getRtcInstanceWithError(editor).undoManager.hasRedo(undoManager, index);
18324
    const transact = (editor, undoManager, locks, callback) => getRtcInstanceWithError(editor).undoManager.transact(undoManager, locks, callback);
18325
    const ignore = (editor, locks, callback) => {
18326
      getRtcInstanceWithError(editor).undoManager.ignore(locks, callback);
18327
    };
18328
    const extra = (editor, undoManager, index, callback1, callback2) => {
18329
      getRtcInstanceWithError(editor).undoManager.extra(undoManager, index, callback1, callback2);
18330
    };
18331
    const matchFormat = (editor, name, vars, node, similar) => getRtcInstanceWithError(editor).formatter.match(name, vars, node, similar);
18332
    const matchAllFormats = (editor, names, vars) => getRtcInstanceWithError(editor).formatter.matchAll(names, vars);
18333
    const matchNodeFormat = (editor, node, name, vars, similar) => getRtcInstanceWithError(editor).formatter.matchNode(node, name, vars, similar);
18334
    const canApplyFormat = (editor, name) => getRtcInstanceWithError(editor).formatter.canApply(name);
18335
    const closestFormat = (editor, names) => getRtcInstanceWithError(editor).formatter.closest(names);
18336
    const applyFormat = (editor, name, vars, node) => {
18337
      getRtcInstanceWithError(editor).formatter.apply(name, vars, node);
18338
    };
18339
    const removeFormat = (editor, name, vars, node, similar) => {
18340
      getRtcInstanceWithError(editor).formatter.remove(name, vars, node, similar);
18341
    };
18342
    const toggleFormat = (editor, name, vars, node) => {
18343
      getRtcInstanceWithError(editor).formatter.toggle(name, vars, node);
18344
    };
18345
    const formatChanged = (editor, registeredFormatListeners, formats, callback, similar, vars) => getRtcInstanceWithError(editor).formatter.formatChanged(registeredFormatListeners, formats, callback, similar, vars);
18346
    const getContent$2 = (editor, args) => getRtcInstanceWithFallback(editor).editor.getContent(args);
18347
    const setContent$2 = (editor, content, args) => getRtcInstanceWithFallback(editor).editor.setContent(content, args);
18348
    const insertContent$1 = (editor, value, details) => getRtcInstanceWithFallback(editor).editor.insertContent(value, details);
18349
    const getSelectedContent = (editor, format, args) => getRtcInstanceWithError(editor).selection.getContent(format, args);
18350
    const addVisual$1 = (editor, elm) => getRtcInstanceWithError(editor).editor.addVisual(elm);
18351
    const bindEvents = editor => getRtcInstanceWithError(editor).init.bindEvents();
18352
    const addAutocompleterDecoration = (editor, range) => getRtcInstanceWithError(editor).autocompleter.addDecoration(range);
18353
    const removeAutocompleterDecoration = editor => getRtcInstanceWithError(editor).autocompleter.removeDecoration();
18354
 
18355
    const getContent$1 = (editor, args = {}) => {
18356
      const format = args.format ? args.format : 'html';
18357
      return getSelectedContent(editor, format, args);
18358
    };
18359
 
18360
    const removeEmpty = text => {
18361
      if (text.dom.length === 0) {
18362
        remove$5(text);
18363
        return Optional.none();
18364
      } else {
18365
        return Optional.some(text);
18366
      }
18367
    };
18368
    const walkPastBookmark = (node, start) => node.filter(elm => BookmarkManager.isBookmarkNode(elm.dom)).bind(start ? nextSibling : prevSibling);
18369
    const merge$1 = (outer, inner, rng, start, schema) => {
18370
      const outerElm = outer.dom;
18371
      const innerElm = inner.dom;
18372
      const oldLength = start ? outerElm.length : innerElm.length;
18373
      if (start) {
18374
        mergeTextNodes(outerElm, innerElm, schema, false, !start);
18375
        rng.setStart(innerElm, oldLength);
18376
      } else {
18377
        mergeTextNodes(innerElm, outerElm, schema, false, !start);
18378
        rng.setEnd(innerElm, oldLength);
18379
      }
18380
    };
18381
    const normalizeTextIfRequired = (inner, start, schema) => {
18382
      parent(inner).each(root => {
18383
        const text = inner.dom;
18384
        if (start && needsToBeNbspLeft(root, CaretPosition(text, 0), schema)) {
18385
          normalizeWhitespaceAfter(text, 0, schema);
18386
        } else if (!start && needsToBeNbspRight(root, CaretPosition(text, text.length), schema)) {
18387
          normalizeWhitespaceBefore(text, text.length, schema);
18388
        }
18389
      });
18390
    };
18391
    const mergeAndNormalizeText = (outerNode, innerNode, rng, start, schema) => {
18392
      outerNode.bind(outer => {
18393
        const normalizer = start ? normalizeWhitespaceBefore : normalizeWhitespaceAfter;
18394
        normalizer(outer.dom, start ? outer.dom.length : 0, schema);
18395
        return innerNode.filter(isText$b).map(inner => merge$1(outer, inner, rng, start, schema));
18396
      }).orThunk(() => {
18397
        const innerTextNode = walkPastBookmark(innerNode, start).or(innerNode).filter(isText$b);
18398
        return innerTextNode.map(inner => normalizeTextIfRequired(inner, start, schema));
18399
      });
18400
    };
18401
    const rngSetContent = (rng, fragment, schema) => {
18402
      const firstChild = Optional.from(fragment.firstChild).map(SugarElement.fromDom);
18403
      const lastChild = Optional.from(fragment.lastChild).map(SugarElement.fromDom);
18404
      rng.deleteContents();
18405
      rng.insertNode(fragment);
18406
      const prevText = firstChild.bind(prevSibling).filter(isText$b).bind(removeEmpty);
18407
      const nextText = lastChild.bind(nextSibling).filter(isText$b).bind(removeEmpty);
18408
      mergeAndNormalizeText(prevText, firstChild, rng, true, schema);
18409
      mergeAndNormalizeText(nextText, lastChild, rng, false, schema);
18410
      rng.collapse(false);
18411
    };
18412
    const setupArgs$2 = (args, content) => ({
18413
      format: 'html',
18414
      ...args,
18415
      set: true,
18416
      selection: true,
18417
      content
18418
    });
18419
    const cleanContent = (editor, args) => {
18420
      if (args.format !== 'raw') {
18421
        const rng = editor.selection.getRng();
18422
        const contextBlock = editor.dom.getParent(rng.commonAncestorContainer, editor.dom.isBlock);
18423
        const contextArgs = contextBlock ? { context: contextBlock.nodeName.toLowerCase() } : {};
18424
        const node = editor.parser.parse(args.content, {
18425
          forced_root_block: false,
18426
          ...contextArgs,
18427
          ...args
18428
        });
18429
        return HtmlSerializer({ validate: false }, editor.schema).serialize(node);
18430
      } else {
18431
        return args.content;
18432
      }
18433
    };
18434
    const setContent$1 = (editor, content, args = {}) => {
18435
      const defaultedArgs = setupArgs$2(args, content);
18436
      preProcessSetContent(editor, defaultedArgs).each(updatedArgs => {
18437
        const cleanedContent = cleanContent(editor, updatedArgs);
18438
        const rng = editor.selection.getRng();
18439
        rngSetContent(rng, rng.createContextualFragment(cleanedContent), editor.schema);
18440
        editor.selection.setRng(rng);
18441
        scrollRangeIntoView(editor, rng);
18442
        postProcessSetContent(editor, cleanedContent, updatedArgs);
18443
      });
18444
    };
18445
 
18446
    const deleteFromCallbackMap = (callbackMap, selector, callback) => {
18447
      if (has$2(callbackMap, selector)) {
18448
        const newCallbacks = filter$5(callbackMap[selector], cb => cb !== callback);
18449
        if (newCallbacks.length === 0) {
18450
          delete callbackMap[selector];
18451
        } else {
18452
          callbackMap[selector] = newCallbacks;
18453
        }
18454
      }
18455
    };
18456
    var SelectorChanged = (dom, editor) => {
18457
      let selectorChangedData;
18458
      let currentSelectors;
18459
      const findMatchingNode = (selector, nodes) => find$2(nodes, node => dom.is(node, selector));
18460
      const getParents = elem => dom.getParents(elem, undefined, dom.getRoot());
18461
      const setup = () => {
18462
        selectorChangedData = {};
18463
        currentSelectors = {};
18464
        editor.on('NodeChange', e => {
18465
          const node = e.element;
18466
          const parents = getParents(node);
18467
          const matchedSelectors = {};
18468
          each$d(selectorChangedData, (callbacks, selector) => {
18469
            findMatchingNode(selector, parents).each(node => {
18470
              if (!currentSelectors[selector]) {
18471
                each$e(callbacks, callback => {
18472
                  callback(true, {
18473
                    node,
18474
                    selector,
18475
                    parents
18476
                  });
18477
                });
18478
                currentSelectors[selector] = callbacks;
18479
              }
18480
              matchedSelectors[selector] = callbacks;
18481
            });
18482
          });
18483
          each$d(currentSelectors, (callbacks, selector) => {
18484
            if (!matchedSelectors[selector]) {
18485
              delete currentSelectors[selector];
18486
              each$e(callbacks, callback => {
18487
                callback(false, {
18488
                  node,
18489
                  selector,
18490
                  parents
18491
                });
18492
              });
18493
            }
18494
          });
18495
        });
18496
      };
18497
      return {
18498
        selectorChangedWithUnbind: (selector, callback) => {
18499
          if (!selectorChangedData) {
18500
            setup();
18501
          }
18502
          if (!selectorChangedData[selector]) {
18503
            selectorChangedData[selector] = [];
18504
          }
18505
          selectorChangedData[selector].push(callback);
18506
          findMatchingNode(selector, getParents(editor.selection.getStart())).each(() => {
18507
            currentSelectors[selector] = selectorChangedData[selector];
18508
          });
18509
          return {
18510
            unbind: () => {
18511
              deleteFromCallbackMap(selectorChangedData, selector, callback);
18512
              deleteFromCallbackMap(currentSelectors, selector, callback);
18513
            }
18514
          };
18515
        }
18516
      };
18517
    };
18518
 
18519
    const isAttachedToDom = node => {
18520
      return !!(node && node.ownerDocument) && contains(SugarElement.fromDom(node.ownerDocument), SugarElement.fromDom(node));
18521
    };
18522
    const isValidRange = rng => {
18523
      if (!rng) {
18524
        return false;
18525
      } else {
18526
        return isAttachedToDom(rng.startContainer) && isAttachedToDom(rng.endContainer);
18527
      }
18528
    };
18529
    const EditorSelection = (dom, win, serializer, editor) => {
18530
      let selectedRange;
18531
      let explicitRange;
18532
      const {selectorChangedWithUnbind} = SelectorChanged(dom, editor);
18533
      const setCursorLocation = (node, offset) => {
18534
        const rng = dom.createRng();
18535
        if (isNonNullable(node) && isNonNullable(offset)) {
18536
          rng.setStart(node, offset);
18537
          rng.setEnd(node, offset);
18538
          setRng(rng);
18539
          collapse(false);
18540
        } else {
18541
          moveEndPoint(dom, rng, editor.getBody(), true);
18542
          setRng(rng);
18543
        }
18544
      };
18545
      const getContent = args => getContent$1(editor, args);
18546
      const setContent = (content, args) => setContent$1(editor, content, args);
18547
      const getStart$1 = real => getStart(editor.getBody(), getRng$1(), real);
18548
      const getEnd = real => getEnd$1(editor.getBody(), getRng$1(), real);
18549
      const getBookmark = (type, normalized) => bookmarkManager.getBookmark(type, normalized);
18550
      const moveToBookmark = bookmark => bookmarkManager.moveToBookmark(bookmark);
18551
      const select$1 = (node, content) => {
18552
        select(dom, node, content).each(setRng);
18553
        return node;
18554
      };
18555
      const isCollapsed = () => {
18556
        const rng = getRng$1(), sel = getSel();
18557
        if (!rng || rng.item) {
18558
          return false;
18559
        }
18560
        if (rng.compareEndPoints) {
18561
          return rng.compareEndPoints('StartToEnd', rng) === 0;
18562
        }
18563
        return !sel || rng.collapsed;
18564
      };
18565
      const isEditable = () => {
18566
        const rng = getRng$1();
18567
        const fakeSelectedElements = editor.getBody().querySelectorAll('[data-mce-selected="1"]');
18568
        if (fakeSelectedElements.length > 0) {
18569
          return forall(fakeSelectedElements, el => dom.isEditable(el.parentElement));
18570
        } else {
18571
          return isEditableRange(dom, rng);
18572
        }
18573
      };
18574
      const collapse = toStart => {
18575
        const rng = getRng$1();
18576
        rng.collapse(!!toStart);
18577
        setRng(rng);
18578
      };
18579
      const getSel = () => win.getSelection ? win.getSelection() : win.document.selection;
18580
      const getRng$1 = () => {
18581
        let rng;
18582
        const tryCompareBoundaryPoints = (how, sourceRange, destinationRange) => {
18583
          try {
18584
            return sourceRange.compareBoundaryPoints(how, destinationRange);
18585
          } catch (ex) {
18586
            return -1;
18587
          }
18588
        };
18589
        const doc = win.document;
18590
        if (isNonNullable(editor.bookmark) && !hasFocus(editor)) {
18591
          const bookmark = getRng(editor);
18592
          if (bookmark.isSome()) {
18593
            return bookmark.map(r => processRanges(editor, [r])[0]).getOr(doc.createRange());
18594
          }
18595
        }
18596
        try {
18597
          const selection = getSel();
18598
          if (selection && !isRestrictedNode(selection.anchorNode)) {
18599
            if (selection.rangeCount > 0) {
18600
              rng = selection.getRangeAt(0);
18601
            } else {
18602
              rng = doc.createRange();
18603
            }
18604
            rng = processRanges(editor, [rng])[0];
18605
          }
18606
        } catch (ex) {
18607
        }
18608
        if (!rng) {
18609
          rng = doc.createRange();
18610
        }
18611
        if (isDocument$1(rng.startContainer) && rng.collapsed) {
18612
          const elm = dom.getRoot();
18613
          rng.setStart(elm, 0);
18614
          rng.setEnd(elm, 0);
18615
        }
18616
        if (selectedRange && explicitRange) {
18617
          if (tryCompareBoundaryPoints(rng.START_TO_START, rng, selectedRange) === 0 && tryCompareBoundaryPoints(rng.END_TO_END, rng, selectedRange) === 0) {
18618
            rng = explicitRange;
18619
          } else {
18620
            selectedRange = null;
18621
            explicitRange = null;
18622
          }
18623
        }
18624
        return rng;
18625
      };
18626
      const setRng = (rng, forward) => {
18627
        if (!isValidRange(rng)) {
18628
          return;
18629
        }
18630
        const sel = getSel();
18631
        const evt = editor.dispatch('SetSelectionRange', {
18632
          range: rng,
18633
          forward
18634
        });
18635
        rng = evt.range;
18636
        if (sel) {
18637
          explicitRange = rng;
18638
          try {
18639
            sel.removeAllRanges();
18640
            sel.addRange(rng);
18641
          } catch (ex) {
18642
          }
18643
          if (forward === false && sel.extend) {
18644
            sel.collapse(rng.endContainer, rng.endOffset);
18645
            sel.extend(rng.startContainer, rng.startOffset);
18646
          }
18647
          selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
18648
        }
18649
        if (!rng.collapsed && rng.startContainer === rng.endContainer && (sel === null || sel === void 0 ? void 0 : sel.setBaseAndExtent)) {
18650
          if (rng.endOffset - rng.startOffset < 2) {
18651
            if (rng.startContainer.hasChildNodes()) {
18652
              const node = rng.startContainer.childNodes[rng.startOffset];
18653
              if (node && node.nodeName === 'IMG') {
18654
                sel.setBaseAndExtent(rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset);
18655
                if (sel.anchorNode !== rng.startContainer || sel.focusNode !== rng.endContainer) {
18656
                  sel.setBaseAndExtent(node, 0, node, 1);
18657
                }
18658
              }
18659
            }
18660
          }
18661
        }
18662
        editor.dispatch('AfterSetSelectionRange', {
18663
          range: rng,
18664
          forward
18665
        });
18666
      };
18667
      const setNode = elm => {
18668
        setContent(dom.getOuterHTML(elm));
18669
        return elm;
18670
      };
18671
      const getNode$1 = () => getNode(editor.getBody(), getRng$1());
18672
      const getSelectedBlocks$1 = (startElm, endElm) => getSelectedBlocks(dom, getRng$1(), startElm, endElm);
18673
      const isForward = () => {
18674
        const sel = getSel();
18675
        const anchorNode = sel === null || sel === void 0 ? void 0 : sel.anchorNode;
18676
        const focusNode = sel === null || sel === void 0 ? void 0 : sel.focusNode;
18677
        if (!sel || !anchorNode || !focusNode || isRestrictedNode(anchorNode) || isRestrictedNode(focusNode)) {
18678
          return true;
18679
        }
18680
        const anchorRange = dom.createRng();
18681
        const focusRange = dom.createRng();
18682
        try {
18683
          anchorRange.setStart(anchorNode, sel.anchorOffset);
18684
          anchorRange.collapse(true);
18685
          focusRange.setStart(focusNode, sel.focusOffset);
18686
          focusRange.collapse(true);
18687
        } catch (e) {
18688
          return true;
18689
        }
18690
        return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
18691
      };
18692
      const normalize = () => {
18693
        const rng = getRng$1();
18694
        const sel = getSel();
18695
        if (!hasMultipleRanges(sel) && hasAnyRanges(editor)) {
18696
          const normRng = normalize$2(dom, rng);
18697
          normRng.each(normRng => {
18698
            setRng(normRng, isForward());
18699
          });
18700
          return normRng.getOr(rng);
18701
        }
18702
        return rng;
18703
      };
18704
      const selectorChanged = (selector, callback) => {
18705
        selectorChangedWithUnbind(selector, callback);
18706
        return exports;
18707
      };
18708
      const getScrollContainer = () => {
18709
        let scrollContainer;
18710
        let node = dom.getRoot();
18711
        while (node && node.nodeName !== 'BODY') {
18712
          if (node.scrollHeight > node.clientHeight) {
18713
            scrollContainer = node;
18714
            break;
18715
          }
18716
          node = node.parentNode;
18717
        }
18718
        return scrollContainer;
18719
      };
18720
      const scrollIntoView = (elm, alignToTop) => {
18721
        if (isNonNullable(elm)) {
18722
          scrollElementIntoView(editor, elm, alignToTop);
18723
        } else {
18724
          scrollRangeIntoView(editor, getRng$1(), alignToTop);
18725
        }
18726
      };
18727
      const placeCaretAt = (clientX, clientY) => setRng(fromPoint(clientX, clientY, editor.getDoc()));
18728
      const getBoundingClientRect = () => {
18729
        const rng = getRng$1();
18730
        return rng.collapsed ? CaretPosition.fromRangeStart(rng).getClientRects()[0] : rng.getBoundingClientRect();
18731
      };
18732
      const destroy = () => {
18733
        win = selectedRange = explicitRange = null;
18734
        controlSelection.destroy();
18735
      };
18736
      const expand = (options = { type: 'word' }) => setRng(RangeUtils(dom).expand(getRng$1(), options));
18737
      const exports = {
18738
        dom,
18739
        win,
18740
        serializer,
18741
        editor,
18742
        expand,
18743
        collapse,
18744
        setCursorLocation,
18745
        getContent,
18746
        setContent,
18747
        getBookmark,
18748
        moveToBookmark,
18749
        select: select$1,
18750
        isCollapsed,
18751
        isEditable,
18752
        isForward,
18753
        setNode,
18754
        getNode: getNode$1,
18755
        getSel,
18756
        setRng,
18757
        getRng: getRng$1,
18758
        getStart: getStart$1,
18759
        getEnd,
18760
        getSelectedBlocks: getSelectedBlocks$1,
18761
        normalize,
18762
        selectorChanged,
18763
        selectorChangedWithUnbind,
18764
        getScrollContainer,
18765
        scrollIntoView,
18766
        placeCaretAt,
18767
        getBoundingClientRect,
18768
        destroy
18769
      };
18770
      const bookmarkManager = BookmarkManager(exports);
18771
      const controlSelection = ControlSelection(exports, editor);
18772
      exports.bookmarkManager = bookmarkManager;
18773
      exports.controlSelection = controlSelection;
18774
      return exports;
18775
    };
18776
 
18777
    const register$3 = (htmlParser, settings, dom) => {
18778
      htmlParser.addAttributeFilter('data-mce-tabindex', (nodes, name) => {
18779
        let i = nodes.length;
18780
        while (i--) {
18781
          const node = nodes[i];
18782
          node.attr('tabindex', node.attr('data-mce-tabindex'));
18783
          node.attr(name, null);
18784
        }
18785
      });
18786
      htmlParser.addAttributeFilter('src,href,style', (nodes, name) => {
18787
        const internalName = 'data-mce-' + name;
18788
        const urlConverter = settings.url_converter;
18789
        const urlConverterScope = settings.url_converter_scope;
18790
        let i = nodes.length;
18791
        while (i--) {
18792
          const node = nodes[i];
18793
          let value = node.attr(internalName);
18794
          if (value !== undefined) {
18795
            node.attr(name, value.length > 0 ? value : null);
18796
            node.attr(internalName, null);
18797
          } else {
18798
            value = node.attr(name);
18799
            if (name === 'style') {
18800
              value = dom.serializeStyle(dom.parseStyle(value), node.name);
18801
            } else if (urlConverter) {
18802
              value = urlConverter.call(urlConverterScope, value, name, node.name);
18803
            }
18804
            node.attr(name, value.length > 0 ? value : null);
18805
          }
18806
        }
18807
      });
18808
      htmlParser.addAttributeFilter('class', nodes => {
18809
        let i = nodes.length;
18810
        while (i--) {
18811
          const node = nodes[i];
18812
          let value = node.attr('class');
18813
          if (value) {
18814
            value = value.replace(/(?:^|\s)mce-item-\w+(?!\S)/g, '');
18815
            node.attr('class', value.length > 0 ? value : null);
18816
          }
18817
        }
18818
      });
18819
      htmlParser.addAttributeFilter('data-mce-type', (nodes, name, args) => {
18820
        let i = nodes.length;
18821
        while (i--) {
18822
          const node = nodes[i];
18823
          if (node.attr('data-mce-type') === 'bookmark' && !args.cleanup) {
18824
            const hasChildren = Optional.from(node.firstChild).exists(firstChild => {
18825
              var _a;
18826
              return !isZwsp$1((_a = firstChild.value) !== null && _a !== void 0 ? _a : '');
18827
            });
18828
            if (hasChildren) {
18829
              node.unwrap();
18830
            } else {
18831
              node.remove();
18832
            }
18833
          }
18834
        }
18835
      });
18836
      htmlParser.addNodeFilter('noscript', nodes => {
18837
        var _a;
18838
        let i = nodes.length;
18839
        while (i--) {
18840
          const node = nodes[i].firstChild;
18841
          if (node) {
18842
            node.value = Entities.decode((_a = node.value) !== null && _a !== void 0 ? _a : '');
18843
          }
18844
        }
18845
      });
18846
      htmlParser.addNodeFilter('script,style', (nodes, name) => {
18847
        var _a;
18848
        const trim = value => {
18849
          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, '');
18850
        };
18851
        let i = nodes.length;
18852
        while (i--) {
18853
          const node = nodes[i];
18854
          const firstChild = node.firstChild;
18855
          const value = (_a = firstChild === null || firstChild === void 0 ? void 0 : firstChild.value) !== null && _a !== void 0 ? _a : '';
18856
          if (name === 'script') {
18857
            const type = node.attr('type');
18858
            if (type) {
18859
              node.attr('type', type === 'mce-no/type' ? null : type.replace(/^mce\-/, ''));
18860
            }
18861
            if (settings.element_format === 'xhtml' && firstChild && value.length > 0) {
18862
              firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>';
18863
            }
18864
          } else {
18865
            if (settings.element_format === 'xhtml' && firstChild && value.length > 0) {
18866
              firstChild.value = '<!--\n' + trim(value) + '\n-->';
18867
            }
18868
          }
18869
        }
18870
      });
18871
      htmlParser.addNodeFilter('#comment', nodes => {
18872
        let i = nodes.length;
18873
        while (i--) {
18874
          const node = nodes[i];
18875
          const value = node.value;
18876
          if (settings.preserve_cdata && (value === null || value === void 0 ? void 0 : value.indexOf('[CDATA[')) === 0) {
18877
            node.name = '#cdata';
18878
            node.type = 4;
18879
            node.value = dom.decode(value.replace(/^\[CDATA\[|\]\]$/g, ''));
18880
          } else if ((value === null || value === void 0 ? void 0 : value.indexOf('mce:protected ')) === 0) {
18881
            node.name = '#text';
18882
            node.type = 3;
18883
            node.raw = true;
18884
            node.value = unescape(value).substr(14);
18885
          }
18886
        }
18887
      });
18888
      htmlParser.addNodeFilter('xml:namespace,input', (nodes, name) => {
18889
        let i = nodes.length;
18890
        while (i--) {
18891
          const node = nodes[i];
18892
          if (node.type === 7) {
18893
            node.remove();
18894
          } else if (node.type === 1) {
18895
            if (name === 'input' && !node.attr('type')) {
18896
              node.attr('type', 'text');
18897
            }
18898
          }
18899
        }
18900
      });
18901
      htmlParser.addAttributeFilter('data-mce-type', nodes => {
18902
        each$e(nodes, node => {
18903
          if (node.attr('data-mce-type') === 'format-caret') {
18904
            if (node.isEmpty(htmlParser.schema.getNonEmptyElements())) {
18905
              node.remove();
18906
            } else {
18907
              node.unwrap();
18908
            }
18909
          }
18910
        });
18911
      });
18912
      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) => {
18913
        let i = nodes.length;
18914
        while (i--) {
18915
          nodes[i].attr(name, null);
18916
        }
18917
      });
18918
      if (settings.remove_trailing_brs) {
18919
        addNodeFilter(settings, htmlParser, htmlParser.schema);
18920
      }
18921
    };
18922
    const trimTrailingBr = rootNode => {
18923
      const isBr = node => {
18924
        return (node === null || node === void 0 ? void 0 : node.name) === 'br';
18925
      };
18926
      const brNode1 = rootNode.lastChild;
18927
      if (isBr(brNode1)) {
18928
        const brNode2 = brNode1.prev;
18929
        if (isBr(brNode2)) {
18930
          brNode1.remove();
18931
          brNode2.remove();
18932
        }
18933
      }
18934
    };
18935
 
18936
    const preProcess$1 = (editor, node, args) => {
18937
      let oldDoc;
18938
      const dom = editor.dom;
18939
      let clonedNode = node.cloneNode(true);
18940
      const impl = document.implementation;
18941
      if (impl.createHTMLDocument) {
18942
        const doc = impl.createHTMLDocument('');
18943
        Tools.each(clonedNode.nodeName === 'BODY' ? clonedNode.childNodes : [clonedNode], node => {
18944
          doc.body.appendChild(doc.importNode(node, true));
18945
        });
18946
        if (clonedNode.nodeName !== 'BODY') {
18947
          clonedNode = doc.body.firstChild;
18948
        } else {
18949
          clonedNode = doc.body;
18950
        }
18951
        oldDoc = dom.doc;
18952
        dom.doc = doc;
18953
      }
18954
      firePreProcess(editor, {
18955
        ...args,
18956
        node: clonedNode
18957
      });
18958
      if (oldDoc) {
18959
        dom.doc = oldDoc;
18960
      }
18961
      return clonedNode;
18962
    };
18963
    const shouldFireEvent = (editor, args) => {
18964
      return isNonNullable(editor) && editor.hasEventListeners('PreProcess') && !args.no_events;
18965
    };
18966
    const process$1 = (editor, node, args) => {
18967
      return shouldFireEvent(editor, args) ? preProcess$1(editor, node, args) : node;
18968
    };
18969
 
18970
    const addTempAttr = (htmlParser, tempAttrs, name) => {
18971
      if (Tools.inArray(tempAttrs, name) === -1) {
18972
        htmlParser.addAttributeFilter(name, (nodes, name) => {
18973
          let i = nodes.length;
18974
          while (i--) {
18975
            nodes[i].attr(name, null);
18976
          }
18977
        });
18978
        tempAttrs.push(name);
18979
      }
18980
    };
18981
    const postProcess = (editor, args, content) => {
18982
      if (!args.no_events && editor) {
18983
        const outArgs = firePostProcess(editor, {
18984
          ...args,
18985
          content
18986
        });
18987
        return outArgs.content;
18988
      } else {
18989
        return content;
18990
      }
18991
    };
18992
    const getHtmlFromNode = (dom, node, args) => {
18993
      const html = trim$2(args.getInner ? node.innerHTML : dom.getOuterHTML(node));
18994
      return args.selection || isWsPreserveElement(SugarElement.fromDom(node)) ? html : Tools.trim(html);
18995
    };
18996
    const parseHtml = (htmlParser, html, args) => {
18997
      const parserArgs = args.selection ? {
18998
        forced_root_block: false,
18999
        ...args
19000
      } : args;
19001
      const rootNode = htmlParser.parse(html, parserArgs);
19002
      trimTrailingBr(rootNode);
19003
      return rootNode;
19004
    };
19005
    const serializeNode = (settings, schema, node) => {
19006
      const htmlSerializer = HtmlSerializer(settings, schema);
19007
      return htmlSerializer.serialize(node);
19008
    };
19009
    const toHtml = (editor, settings, schema, rootNode, args) => {
19010
      const content = serializeNode(settings, schema, rootNode);
19011
      return postProcess(editor, args, content);
19012
    };
19013
    const DomSerializerImpl = (settings, editor) => {
19014
      const tempAttrs = ['data-mce-selected'];
19015
      const defaultedSettings = {
19016
        entity_encoding: 'named',
19017
        remove_trailing_brs: true,
19018
        pad_empty_with_br: false,
19019
        ...settings
19020
      };
19021
      const dom = editor && editor.dom ? editor.dom : DOMUtils.DOM;
19022
      const schema = editor && editor.schema ? editor.schema : Schema(defaultedSettings);
19023
      const htmlParser = DomParser(defaultedSettings, schema);
19024
      register$3(htmlParser, defaultedSettings, dom);
19025
      const serialize = (node, parserArgs = {}) => {
19026
        const args = {
19027
          format: 'html',
19028
          ...parserArgs
19029
        };
19030
        const targetNode = process$1(editor, node, args);
19031
        const html = getHtmlFromNode(dom, targetNode, args);
19032
        const rootNode = parseHtml(htmlParser, html, args);
19033
        return args.format === 'tree' ? rootNode : toHtml(editor, defaultedSettings, schema, rootNode, args);
19034
      };
19035
      return {
19036
        schema,
19037
        addNodeFilter: htmlParser.addNodeFilter,
19038
        addAttributeFilter: htmlParser.addAttributeFilter,
19039
        serialize: serialize,
19040
        addRules: schema.addValidElements,
19041
        setRules: schema.setValidElements,
19042
        addTempAttr: curry(addTempAttr, htmlParser, tempAttrs),
19043
        getTempAttrs: constant(tempAttrs),
19044
        getNodeFilters: htmlParser.getNodeFilters,
19045
        getAttributeFilters: htmlParser.getAttributeFilters,
19046
        removeNodeFilter: htmlParser.removeNodeFilter,
19047
        removeAttributeFilter: htmlParser.removeAttributeFilter
19048
      };
19049
    };
19050
 
19051
    const DomSerializer = (settings, editor) => {
19052
      const domSerializer = DomSerializerImpl(settings, editor);
19053
      return {
19054
        schema: domSerializer.schema,
19055
        addNodeFilter: domSerializer.addNodeFilter,
19056
        addAttributeFilter: domSerializer.addAttributeFilter,
19057
        serialize: domSerializer.serialize,
19058
        addRules: domSerializer.addRules,
19059
        setRules: domSerializer.setRules,
19060
        addTempAttr: domSerializer.addTempAttr,
19061
        getTempAttrs: domSerializer.getTempAttrs,
19062
        getNodeFilters: domSerializer.getNodeFilters,
19063
        getAttributeFilters: domSerializer.getAttributeFilters,
19064
        removeNodeFilter: domSerializer.removeNodeFilter,
19065
        removeAttributeFilter: domSerializer.removeAttributeFilter
19066
      };
19067
    };
19068
 
19069
    const defaultFormat$1 = 'html';
19070
    const setupArgs$1 = (args, format) => ({
19071
      ...args,
19072
      format,
19073
      get: true,
19074
      getInner: true
19075
    });
19076
    const getContent = (editor, args = {}) => {
19077
      const format = args.format ? args.format : defaultFormat$1;
19078
      const defaultedArgs = setupArgs$1(args, format);
19079
      return preProcessGetContent(editor, defaultedArgs).fold(identity, updatedArgs => {
19080
        const content = getContent$2(editor, updatedArgs);
19081
        return postProcessGetContent(editor, content, updatedArgs);
19082
      });
19083
    };
19084
 
19085
    const defaultFormat = 'html';
19086
    const setupArgs = (args, content) => ({
19087
      format: defaultFormat,
19088
      ...args,
19089
      set: true,
19090
      content
19091
    });
19092
    const setContent = (editor, content, args = {}) => {
19093
      const defaultedArgs = setupArgs(args, content);
19094
      return preProcessSetContent(editor, defaultedArgs).map(updatedArgs => {
19095
        const result = setContent$2(editor, updatedArgs.content, updatedArgs);
19096
        postProcessSetContent(editor, result.html, updatedArgs);
19097
        return result.content;
19098
      }).getOr(content);
19099
    };
19100
 
19101
    const removedOptions = ('autoresize_on_init,content_editable_state,padd_empty_with_br,block_elements,' + 'boolean_attributes,editor_deselector,editor_selector,elements,file_browser_callback_types,filepicker_validator_handler,' + 'force_hex_style_colors,force_p_newlines,gecko_spellcheck,images_dataimg_filter,media_scripts,mode,move_caret_before_on_enter_elements,' + 'non_empty_elements,self_closing_elements,short_ended_elements,special,spellchecker_select_languages,spellchecker_whitelist,' + 'tab_focus,tabfocus_elements,table_responsive_width,text_block_elements,text_inline_elements,toolbar_drawer,types,validate,whitespace_elements,' + 'paste_enable_default_filters,paste_filter_drop,paste_word_valid_elements,paste_retain_style_properties,paste_convert_word_fake_lists').split(',');
19102
    const deprecatedOptions = 'template_cdate_classes,template_mdate_classes,template_selected_content_classes,template_preview_replace_values,template_replace_values,templates,template_cdate_format,template_mdate_format'.split(',');
19103
    const removedPlugins = 'bbcode,colorpicker,contextmenu,fullpage,legacyoutput,spellchecker,textcolor'.split(',');
19104
    const deprecatedPlugins = [
19105
      {
19106
        name: 'template',
19107
        replacedWith: 'Advanced Template'
19108
      },
19109
      { name: 'rtc' }
19110
    ];
19111
    const getMatchingOptions = (options, searchingFor) => {
19112
      const settingNames = filter$5(searchingFor, setting => has$2(options, setting));
19113
      return sort(settingNames);
19114
    };
19115
    const getRemovedOptions = options => {
19116
      const settingNames = getMatchingOptions(options, removedOptions);
19117
      const forcedRootBlock = options.forced_root_block;
19118
      if (forcedRootBlock === false || forcedRootBlock === '') {
19119
        settingNames.push('forced_root_block (false only)');
19120
      }
19121
      return sort(settingNames);
19122
    };
19123
    const getDeprecatedOptions = options => getMatchingOptions(options, deprecatedOptions);
19124
    const getMatchingPlugins = (options, searchingFor) => {
19125
      const plugins = Tools.makeMap(options.plugins, ' ');
19126
      const hasPlugin = plugin => has$2(plugins, plugin);
19127
      const pluginNames = filter$5(searchingFor, hasPlugin);
19128
      return sort(pluginNames);
19129
    };
19130
    const getRemovedPlugins = options => getMatchingPlugins(options, removedPlugins);
19131
    const getDeprecatedPlugins = options => getMatchingPlugins(options, deprecatedPlugins.map(entry => entry.name));
19132
    const logRemovedWarnings = (rawOptions, normalizedOptions) => {
19133
      const removedOptions = getRemovedOptions(rawOptions);
19134
      const removedPlugins = getRemovedPlugins(normalizedOptions);
19135
      const hasRemovedPlugins = removedPlugins.length > 0;
19136
      const hasRemovedOptions = removedOptions.length > 0;
19137
      const isLegacyMobileTheme = normalizedOptions.theme === 'mobile';
19138
      if (hasRemovedPlugins || hasRemovedOptions || isLegacyMobileTheme) {
19139
        const listJoiner = '\n- ';
19140
        const themesMessage = isLegacyMobileTheme ? `\n\nThemes:${ listJoiner }mobile` : '';
19141
        const pluginsMessage = hasRemovedPlugins ? `\n\nPlugins:${ listJoiner }${ removedPlugins.join(listJoiner) }` : '';
19142
        const optionsMessage = hasRemovedOptions ? `\n\nOptions:${ listJoiner }${ removedOptions.join(listJoiner) }` : '';
19143
        console.warn('The following deprecated features are currently enabled and have been removed in TinyMCE 6.0. These features will no longer work and should be removed from the TinyMCE configuration. ' + 'See https://www.tiny.cloud/docs/tinymce/6/migration-from-5x/ for more information.' + themesMessage + pluginsMessage + optionsMessage);
19144
      }
19145
    };
19146
    const getPluginDescription = name => find$2(deprecatedPlugins, entry => entry.name === name).fold(() => name, entry => {
19147
      if (entry.replacedWith) {
19148
        return `${ name }, replaced by ${ entry.replacedWith }`;
19149
      } else {
19150
        return name;
19151
      }
19152
    });
19153
    const logDeprecatedWarnings = (rawOptions, normalizedOptions) => {
19154
      const deprecatedOptions = getDeprecatedOptions(rawOptions);
19155
      const deprecatedPlugins = getDeprecatedPlugins(normalizedOptions);
19156
      const hasDeprecatedPlugins = deprecatedPlugins.length > 0;
19157
      const hasDeprecatedOptions = deprecatedOptions.length > 0;
19158
      if (hasDeprecatedPlugins || hasDeprecatedOptions) {
19159
        const listJoiner = '\n- ';
19160
        const pluginsMessage = hasDeprecatedPlugins ? `\n\nPlugins:${ listJoiner }${ deprecatedPlugins.map(getPluginDescription).join(listJoiner) }` : '';
19161
        const optionsMessage = hasDeprecatedOptions ? `\n\nOptions:${ listJoiner }${ deprecatedOptions.join(listJoiner) }` : '';
19162
        console.warn('The following deprecated features are currently enabled but will be removed soon.' + pluginsMessage + optionsMessage);
19163
      }
19164
    };
19165
    const logWarnings = (rawOptions, normalizedOptions) => {
19166
      logRemovedWarnings(rawOptions, normalizedOptions);
19167
      logDeprecatedWarnings(rawOptions, normalizedOptions);
19168
    };
19169
 
19170
    const DOM$8 = DOMUtils.DOM;
19171
    const restoreOriginalStyles = editor => {
19172
      DOM$8.setStyle(editor.id, 'display', editor.orgDisplay);
19173
    };
19174
    const safeDestroy = x => Optional.from(x).each(x => x.destroy());
19175
    const clearDomReferences = editor => {
19176
      const ed = editor;
19177
      ed.contentAreaContainer = ed.formElement = ed.container = ed.editorContainer = null;
19178
      ed.bodyElement = ed.contentDocument = ed.contentWindow = null;
19179
      ed.iframeElement = ed.targetElm = null;
19180
      const selection = editor.selection;
19181
      if (selection) {
19182
        const dom = selection.dom;
19183
        ed.selection = selection.win = selection.dom = dom.doc = null;
19184
      }
19185
    };
19186
    const restoreForm = editor => {
19187
      const form = editor.formElement;
19188
      if (form) {
19189
        if (form._mceOldSubmit) {
19190
          form.submit = form._mceOldSubmit;
19191
          delete form._mceOldSubmit;
19192
        }
19193
        DOM$8.unbind(form, 'submit reset', editor.formEventDelegate);
19194
      }
19195
    };
19196
    const remove$1 = editor => {
19197
      if (!editor.removed) {
19198
        const {_selectionOverrides, editorUpload} = editor;
19199
        const body = editor.getBody();
19200
        const element = editor.getElement();
19201
        if (body) {
19202
          editor.save({ is_removing: true });
19203
        }
19204
        editor.removed = true;
19205
        editor.unbindAllNativeEvents();
19206
        if (editor.hasHiddenInput && isNonNullable(element === null || element === void 0 ? void 0 : element.nextSibling)) {
19207
          DOM$8.remove(element.nextSibling);
19208
        }
19209
        fireRemove(editor);
19210
        editor.editorManager.remove(editor);
19211
        if (!editor.inline && body) {
19212
          restoreOriginalStyles(editor);
19213
        }
19214
        fireDetach(editor);
19215
        DOM$8.remove(editor.getContainer());
19216
        safeDestroy(_selectionOverrides);
19217
        safeDestroy(editorUpload);
19218
        editor.destroy();
19219
      }
19220
    };
19221
    const destroy = (editor, automatic) => {
19222
      const {selection, dom} = editor;
19223
      if (editor.destroyed) {
19224
        return;
19225
      }
19226
      if (!automatic && !editor.removed) {
19227
        editor.remove();
19228
        return;
19229
      }
19230
      if (!automatic) {
19231
        editor.editorManager.off('beforeunload', editor._beforeUnload);
19232
        if (editor.theme && editor.theme.destroy) {
19233
          editor.theme.destroy();
19234
        }
19235
        safeDestroy(selection);
19236
        safeDestroy(dom);
19237
      }
19238
      restoreForm(editor);
19239
      clearDomReferences(editor);
19240
      editor.destroyed = true;
19241
    };
19242
 
19243
    const CreateIconManager = () => {
19244
      const lookup = {};
19245
      const add = (id, iconPack) => {
19246
        lookup[id] = iconPack;
19247
      };
19248
      const get = id => {
19249
        if (lookup[id]) {
19250
          return lookup[id];
19251
        } else {
19252
          return { icons: {} };
19253
        }
19254
      };
19255
      const has = id => has$2(lookup, id);
19256
      return {
19257
        add,
19258
        get,
19259
        has
19260
      };
19261
    };
19262
    const IconManager = CreateIconManager();
19263
 
19264
    const ModelManager = AddOnManager.ModelManager;
19265
 
19266
    const getProp = (propName, elm) => {
19267
      const rawElm = elm.dom;
19268
      return rawElm[propName];
19269
    };
19270
    const getComputedSizeProp = (propName, elm) => parseInt(get$7(elm, propName), 10);
19271
    const getClientWidth = curry(getProp, 'clientWidth');
19272
    const getClientHeight = curry(getProp, 'clientHeight');
19273
    const getMarginTop = curry(getComputedSizeProp, 'margin-top');
19274
    const getMarginLeft = curry(getComputedSizeProp, 'margin-left');
19275
    const getBoundingClientRect = elm => elm.dom.getBoundingClientRect();
19276
    const isInsideElementContentArea = (bodyElm, clientX, clientY) => {
19277
      const clientWidth = getClientWidth(bodyElm);
19278
      const clientHeight = getClientHeight(bodyElm);
19279
      return clientX >= 0 && clientY >= 0 && clientX <= clientWidth && clientY <= clientHeight;
19280
    };
19281
    const transpose = (inline, elm, clientX, clientY) => {
19282
      const clientRect = getBoundingClientRect(elm);
19283
      const deltaX = inline ? clientRect.left + elm.dom.clientLeft + getMarginLeft(elm) : 0;
19284
      const deltaY = inline ? clientRect.top + elm.dom.clientTop + getMarginTop(elm) : 0;
19285
      const x = clientX - deltaX;
19286
      const y = clientY - deltaY;
19287
      return {
19288
        x,
19289
        y
19290
      };
19291
    };
19292
    const isXYInContentArea = (editor, clientX, clientY) => {
19293
      const bodyElm = SugarElement.fromDom(editor.getBody());
19294
      const targetElm = editor.inline ? bodyElm : documentElement(bodyElm);
19295
      const transposedPoint = transpose(editor.inline, targetElm, clientX, clientY);
19296
      return isInsideElementContentArea(targetElm, transposedPoint.x, transposedPoint.y);
19297
    };
19298
    const fromDomSafe = node => Optional.from(node).map(SugarElement.fromDom);
19299
    const isEditorAttachedToDom = editor => {
19300
      const rawContainer = editor.inline ? editor.getBody() : editor.getContentAreaContainer();
19301
      return fromDomSafe(rawContainer).map(inBody).getOr(false);
19302
    };
19303
 
19304
    var NotificationManagerImpl = () => {
19305
      const unimplemented = () => {
19306
        throw new Error('Theme did not provide a NotificationManager implementation.');
19307
      };
19308
      return {
19309
        open: unimplemented,
19310
        close: unimplemented,
19311
        getArgs: unimplemented
19312
      };
19313
    };
19314
 
19315
    const NotificationManager = editor => {
19316
      const notifications = [];
19317
      const getImplementation = () => {
19318
        const theme = editor.theme;
19319
        return theme && theme.getNotificationManagerImpl ? theme.getNotificationManagerImpl() : NotificationManagerImpl();
19320
      };
19321
      const getTopNotification = () => {
19322
        return Optional.from(notifications[0]);
19323
      };
19324
      const isEqual = (a, b) => {
19325
        return a.type === b.type && a.text === b.text && !a.progressBar && !a.timeout && !b.progressBar && !b.timeout;
19326
      };
19327
      const reposition = () => {
19328
        each$e(notifications, notification => {
19329
          notification.reposition();
19330
        });
19331
      };
19332
      const addNotification = notification => {
19333
        notifications.push(notification);
19334
      };
19335
      const closeNotification = notification => {
19336
        findIndex$2(notifications, otherNotification => {
19337
          return otherNotification === notification;
19338
        }).each(index => {
19339
          notifications.splice(index, 1);
19340
        });
19341
      };
19342
      const open = (spec, fireEvent = true) => {
19343
        if (editor.removed || !isEditorAttachedToDom(editor)) {
19344
          return {};
19345
        }
19346
        if (fireEvent) {
19347
          editor.dispatch('BeforeOpenNotification', { notification: spec });
19348
        }
19349
        return find$2(notifications, notification => {
19350
          return isEqual(getImplementation().getArgs(notification), spec);
19351
        }).getOrThunk(() => {
19352
          editor.editorManager.setActive(editor);
19353
          const notification = getImplementation().open(spec, () => {
19354
            closeNotification(notification);
19355
            reposition();
19356
            if (hasEditorOrUiFocus(editor)) {
19357
              getTopNotification().fold(() => editor.focus(), top => focus$1(SugarElement.fromDom(top.getEl())));
19358
            }
19359
          });
19360
          addNotification(notification);
19361
          reposition();
19362
          editor.dispatch('OpenNotification', { notification: { ...notification } });
19363
          return notification;
19364
        });
19365
      };
19366
      const close = () => {
19367
        getTopNotification().each(notification => {
19368
          getImplementation().close(notification);
19369
          closeNotification(notification);
19370
          reposition();
19371
        });
19372
      };
19373
      const getNotifications = constant(notifications);
19374
      const registerEvents = editor => {
19375
        editor.on('SkinLoaded', () => {
19376
          const serviceMessage = getServiceMessage(editor);
19377
          if (serviceMessage) {
19378
            open({
19379
              text: serviceMessage,
19380
              type: 'warning',
19381
              timeout: 0
19382
            }, false);
19383
          }
19384
          reposition();
19385
        });
19386
        editor.on('show ResizeEditor ResizeWindow NodeChange', () => {
19387
          requestAnimationFrame(reposition);
19388
        });
19389
        editor.on('remove', () => {
19390
          each$e(notifications.slice(), notification => {
19391
            getImplementation().close(notification);
19392
          });
19393
        });
19394
      };
19395
      registerEvents(editor);
19396
      return {
19397
        open,
19398
        close,
19399
        getNotifications
19400
      };
19401
    };
19402
 
19403
    const PluginManager = AddOnManager.PluginManager;
19404
 
19405
    const ThemeManager = AddOnManager.ThemeManager;
19406
 
19407
    var WindowManagerImpl = () => {
19408
      const unimplemented = () => {
19409
        throw new Error('Theme did not provide a WindowManager implementation.');
19410
      };
19411
      return {
19412
        open: unimplemented,
19413
        openUrl: unimplemented,
19414
        alert: unimplemented,
19415
        confirm: unimplemented,
19416
        close: unimplemented
19417
      };
19418
    };
19419
 
19420
    const WindowManager = editor => {
19421
      let dialogs = [];
19422
      const getImplementation = () => {
19423
        const theme = editor.theme;
19424
        return theme && theme.getWindowManagerImpl ? theme.getWindowManagerImpl() : WindowManagerImpl();
19425
      };
19426
      const funcBind = (scope, f) => {
19427
        return (...args) => {
19428
          return f ? f.apply(scope, args) : undefined;
19429
        };
19430
      };
19431
      const fireOpenEvent = dialog => {
19432
        editor.dispatch('OpenWindow', { dialog });
19433
      };
19434
      const fireCloseEvent = dialog => {
19435
        editor.dispatch('CloseWindow', { dialog });
19436
      };
19437
      const addDialog = dialog => {
19438
        dialogs.push(dialog);
19439
        fireOpenEvent(dialog);
19440
      };
19441
      const closeDialog = dialog => {
19442
        fireCloseEvent(dialog);
19443
        dialogs = filter$5(dialogs, otherDialog => {
19444
          return otherDialog !== dialog;
19445
        });
19446
        if (dialogs.length === 0) {
19447
          editor.focus();
19448
        }
19449
      };
19450
      const getTopDialog = () => {
19451
        return Optional.from(dialogs[dialogs.length - 1]);
19452
      };
19453
      const storeSelectionAndOpenDialog = openDialog => {
19454
        editor.editorManager.setActive(editor);
19455
        store(editor);
19456
        editor.ui.show();
19457
        const dialog = openDialog();
19458
        addDialog(dialog);
19459
        return dialog;
19460
      };
19461
      const open = (args, params) => {
19462
        return storeSelectionAndOpenDialog(() => getImplementation().open(args, params, closeDialog));
19463
      };
19464
      const openUrl = args => {
19465
        return storeSelectionAndOpenDialog(() => getImplementation().openUrl(args, closeDialog));
19466
      };
19467
      const alert = (message, callback, scope) => {
19468
        const windowManagerImpl = getImplementation();
19469
        windowManagerImpl.alert(message, funcBind(scope ? scope : windowManagerImpl, callback));
19470
      };
19471
      const confirm = (message, callback, scope) => {
19472
        const windowManagerImpl = getImplementation();
19473
        windowManagerImpl.confirm(message, funcBind(scope ? scope : windowManagerImpl, callback));
19474
      };
19475
      const close = () => {
19476
        getTopDialog().each(dialog => {
19477
          getImplementation().close(dialog);
19478
          closeDialog(dialog);
19479
        });
19480
      };
19481
      editor.on('remove', () => {
19482
        each$e(dialogs, dialog => {
19483
          getImplementation().close(dialog);
19484
        });
19485
      });
19486
      return {
19487
        open,
19488
        openUrl,
19489
        alert,
19490
        confirm,
19491
        close
19492
      };
19493
    };
19494
 
19495
    const displayNotification = (editor, message) => {
19496
      editor.notificationManager.open({
19497
        type: 'error',
19498
        text: message
19499
      });
19500
    };
19501
    const displayError = (editor, message) => {
19502
      if (editor._skinLoaded) {
19503
        displayNotification(editor, message);
19504
      } else {
19505
        editor.on('SkinLoaded', () => {
19506
          displayNotification(editor, message);
19507
        });
19508
      }
19509
    };
19510
    const uploadError = (editor, message) => {
19511
      displayError(editor, I18n.translate([
19512
        'Failed to upload image: {0}',
19513
        message
19514
      ]));
19515
    };
19516
    const logError = (editor, errorType, msg) => {
19517
      fireError(editor, errorType, { message: msg });
19518
      console.error(msg);
19519
    };
19520
    const createLoadError = (type, url, name) => name ? `Failed to load ${ type }: ${ name } from url ${ url }` : `Failed to load ${ type } url: ${ url }`;
19521
    const pluginLoadError = (editor, url, name) => {
19522
      logError(editor, 'PluginLoadError', createLoadError('plugin', url, name));
19523
    };
19524
    const iconsLoadError = (editor, url, name) => {
19525
      logError(editor, 'IconsLoadError', createLoadError('icons', url, name));
19526
    };
19527
    const languageLoadError = (editor, url, name) => {
19528
      logError(editor, 'LanguageLoadError', createLoadError('language', url, name));
19529
    };
19530
    const themeLoadError = (editor, url, name) => {
19531
      logError(editor, 'ThemeLoadError', createLoadError('theme', url, name));
19532
    };
19533
    const modelLoadError = (editor, url, name) => {
19534
      logError(editor, 'ModelLoadError', createLoadError('model', url, name));
19535
    };
19536
    const pluginInitError = (editor, name, err) => {
19537
      const message = I18n.translate([
19538
        'Failed to initialize plugin: {0}',
19539
        name
19540
      ]);
19541
      fireError(editor, 'PluginLoadError', { message });
19542
      initError(message, err);
19543
      displayError(editor, message);
19544
    };
19545
    const initError = (message, ...x) => {
19546
      const console = window.console;
19547
      if (console) {
19548
        if (console.error) {
19549
          console.error(message, ...x);
19550
        } else {
19551
          console.log(message, ...x);
19552
        }
19553
      }
19554
    };
19555
 
19556
    const isContentCssSkinName = url => /^[a-z0-9\-]+$/i.test(url);
19557
    const toContentSkinResourceName = url => 'content/' + url + '/content.css';
19558
    const isBundledCssSkinName = url => tinymce.Resource.has(toContentSkinResourceName(url));
19559
    const getContentCssUrls = editor => {
19560
      return transformToUrls(editor, getContentCss(editor));
19561
    };
19562
    const getFontCssUrls = editor => {
19563
      return transformToUrls(editor, getFontCss(editor));
19564
    };
19565
    const transformToUrls = (editor, cssLinks) => {
19566
      const skinUrl = editor.editorManager.baseURL + '/skins/content';
19567
      const suffix = editor.editorManager.suffix;
19568
      const contentCssFile = `content${ suffix }.css`;
19569
      return map$3(cssLinks, url => {
19570
        if (isBundledCssSkinName(url)) {
19571
          return url;
19572
        } else if (isContentCssSkinName(url) && !editor.inline) {
19573
          return `${ skinUrl }/${ url }/${ contentCssFile }`;
19574
        } else {
19575
          return editor.documentBaseURI.toAbsolute(url);
19576
        }
19577
      });
19578
    };
19579
    const appendContentCssFromSettings = editor => {
19580
      editor.contentCSS = editor.contentCSS.concat(getContentCssUrls(editor), getFontCssUrls(editor));
19581
    };
19582
 
19583
    const getAllImages = elm => {
19584
      return elm ? from(elm.getElementsByTagName('img')) : [];
19585
    };
19586
    const ImageScanner = (uploadStatus, blobCache) => {
19587
      const cachedPromises = {};
19588
      const findAll = (elm, predicate = always) => {
19589
        const images = filter$5(getAllImages(elm), img => {
19590
          const src = img.src;
19591
          if (img.hasAttribute('data-mce-bogus')) {
19592
            return false;
19593
          }
19594
          if (img.hasAttribute('data-mce-placeholder')) {
19595
            return false;
19596
          }
19597
          if (!src || src === Env.transparentSrc) {
19598
            return false;
19599
          }
19600
          if (startsWith(src, 'blob:')) {
19601
            return !uploadStatus.isUploaded(src) && predicate(img);
19602
          }
19603
          if (startsWith(src, 'data:')) {
19604
            return predicate(img);
19605
          }
19606
          return false;
19607
        });
19608
        const promises = map$3(images, img => {
19609
          const imageSrc = img.src;
19610
          if (has$2(cachedPromises, imageSrc)) {
19611
            return cachedPromises[imageSrc].then(imageInfo => {
19612
              if (isString(imageInfo)) {
19613
                return imageInfo;
19614
              } else {
19615
                return {
19616
                  image: img,
19617
                  blobInfo: imageInfo.blobInfo
19618
                };
19619
              }
19620
            });
19621
          } else {
19622
            const newPromise = imageToBlobInfo(blobCache, imageSrc).then(blobInfo => {
19623
              delete cachedPromises[imageSrc];
19624
              return {
19625
                image: img,
19626
                blobInfo
19627
              };
19628
            }).catch(error => {
19629
              delete cachedPromises[imageSrc];
19630
              return error;
19631
            });
19632
            cachedPromises[imageSrc] = newPromise;
19633
            return newPromise;
19634
          }
19635
        });
19636
        return Promise.all(promises);
19637
      };
19638
      return { findAll };
19639
    };
19640
 
19641
    const UploadStatus = () => {
19642
      const PENDING = 1, UPLOADED = 2;
19643
      let blobUriStatuses = {};
19644
      const createStatus = (status, resultUri) => {
19645
        return {
19646
          status,
19647
          resultUri
19648
        };
19649
      };
19650
      const hasBlobUri = blobUri => {
19651
        return blobUri in blobUriStatuses;
19652
      };
19653
      const getResultUri = blobUri => {
19654
        const result = blobUriStatuses[blobUri];
19655
        return result ? result.resultUri : null;
19656
      };
19657
      const isPending = blobUri => {
19658
        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === PENDING : false;
19659
      };
19660
      const isUploaded = blobUri => {
19661
        return hasBlobUri(blobUri) ? blobUriStatuses[blobUri].status === UPLOADED : false;
19662
      };
19663
      const markPending = blobUri => {
19664
        blobUriStatuses[blobUri] = createStatus(PENDING, null);
19665
      };
19666
      const markUploaded = (blobUri, resultUri) => {
19667
        blobUriStatuses[blobUri] = createStatus(UPLOADED, resultUri);
19668
      };
19669
      const removeFailed = blobUri => {
19670
        delete blobUriStatuses[blobUri];
19671
      };
19672
      const destroy = () => {
19673
        blobUriStatuses = {};
19674
      };
19675
      return {
19676
        hasBlobUri,
19677
        getResultUri,
19678
        isPending,
19679
        isUploaded,
19680
        markPending,
19681
        markUploaded,
19682
        removeFailed,
19683
        destroy
19684
      };
19685
    };
19686
 
19687
    let count = 0;
19688
    const seed = () => {
19689
      const rnd = () => {
19690
        return Math.round(Math.random() * 4294967295).toString(36);
19691
      };
19692
      const now = new Date().getTime();
19693
      return 's' + now.toString(36) + rnd() + rnd() + rnd();
19694
    };
19695
    const uuid = prefix => {
19696
      return prefix + count++ + seed();
19697
    };
19698
 
19699
    const BlobCache = () => {
19700
      let cache = [];
19701
      const mimeToExt = mime => {
19702
        const mimes = {
19703
          'image/jpeg': 'jpg',
19704
          'image/jpg': 'jpg',
19705
          'image/gif': 'gif',
19706
          'image/png': 'png',
19707
          'image/apng': 'apng',
19708
          'image/avif': 'avif',
19709
          'image/svg+xml': 'svg',
19710
          'image/webp': 'webp',
19711
          'image/bmp': 'bmp',
19712
          'image/tiff': 'tiff'
19713
        };
19714
        return mimes[mime.toLowerCase()] || 'dat';
19715
      };
19716
      const create = (o, blob, base64, name, filename) => {
19717
        if (isString(o)) {
19718
          const id = o;
19719
          return toBlobInfo({
19720
            id,
19721
            name,
19722
            filename,
19723
            blob: blob,
19724
            base64: base64
19725
          });
19726
        } else if (isObject(o)) {
19727
          return toBlobInfo(o);
19728
        } else {
19729
          throw new Error('Unknown input type');
19730
        }
19731
      };
19732
      const toBlobInfo = o => {
19733
        if (!o.blob || !o.base64) {
19734
          throw new Error('blob and base64 representations of the image are required for BlobInfo to be created');
19735
        }
19736
        const id = o.id || uuid('blobid');
19737
        const name = o.name || id;
19738
        const blob = o.blob;
19739
        return {
19740
          id: constant(id),
19741
          name: constant(name),
19742
          filename: constant(o.filename || name + '.' + mimeToExt(blob.type)),
19743
          blob: constant(blob),
19744
          base64: constant(o.base64),
19745
          blobUri: constant(o.blobUri || URL.createObjectURL(blob)),
19746
          uri: constant(o.uri)
19747
        };
19748
      };
19749
      const add = blobInfo => {
19750
        if (!get(blobInfo.id())) {
19751
          cache.push(blobInfo);
19752
        }
19753
      };
19754
      const findFirst = predicate => find$2(cache, predicate).getOrUndefined();
19755
      const get = id => findFirst(cachedBlobInfo => cachedBlobInfo.id() === id);
19756
      const getByUri = blobUri => findFirst(blobInfo => blobInfo.blobUri() === blobUri);
19757
      const getByData = (base64, type) => findFirst(blobInfo => blobInfo.base64() === base64 && blobInfo.blob().type === type);
19758
      const removeByUri = blobUri => {
19759
        cache = filter$5(cache, blobInfo => {
19760
          if (blobInfo.blobUri() === blobUri) {
19761
            URL.revokeObjectURL(blobInfo.blobUri());
19762
            return false;
19763
          }
19764
          return true;
19765
        });
19766
      };
19767
      const destroy = () => {
19768
        each$e(cache, cachedBlobInfo => {
19769
          URL.revokeObjectURL(cachedBlobInfo.blobUri());
19770
        });
19771
        cache = [];
19772
      };
19773
      return {
19774
        create,
19775
        add,
19776
        get,
19777
        getByUri,
19778
        getByData,
19779
        findFirst,
19780
        removeByUri,
19781
        destroy
19782
      };
19783
    };
19784
 
19785
    const Uploader = (uploadStatus, settings) => {
19786
      const pendingPromises = {};
19787
      const pathJoin = (path1, path2) => {
19788
        if (path1) {
19789
          return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, '');
19790
        }
19791
        return path2;
19792
      };
19793
      const defaultHandler = (blobInfo, progress) => new Promise((success, failure) => {
19794
        const xhr = new XMLHttpRequest();
19795
        xhr.open('POST', settings.url);
19796
        xhr.withCredentials = settings.credentials;
19797
        xhr.upload.onprogress = e => {
19798
          progress(e.loaded / e.total * 100);
19799
        };
19800
        xhr.onerror = () => {
19801
          failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status);
19802
        };
19803
        xhr.onload = () => {
19804
          if (xhr.status < 200 || xhr.status >= 300) {
19805
            failure('HTTP Error: ' + xhr.status);
19806
            return;
19807
          }
19808
          const json = JSON.parse(xhr.responseText);
19809
          if (!json || !isString(json.location)) {
19810
            failure('Invalid JSON: ' + xhr.responseText);
19811
            return;
19812
          }
19813
          success(pathJoin(settings.basePath, json.location));
19814
        };
19815
        const formData = new FormData();
19816
        formData.append('file', blobInfo.blob(), blobInfo.filename());
19817
        xhr.send(formData);
19818
      });
19819
      const uploadHandler = isFunction(settings.handler) ? settings.handler : defaultHandler;
19820
      const noUpload = () => new Promise(resolve => {
19821
        resolve([]);
19822
      });
19823
      const handlerSuccess = (blobInfo, url) => ({
19824
        url,
19825
        blobInfo,
19826
        status: true
19827
      });
19828
      const handlerFailure = (blobInfo, error) => ({
19829
        url: '',
19830
        blobInfo,
19831
        status: false,
19832
        error
19833
      });
19834
      const resolvePending = (blobUri, result) => {
19835
        Tools.each(pendingPromises[blobUri], resolve => {
19836
          resolve(result);
19837
        });
19838
        delete pendingPromises[blobUri];
19839
      };
19840
      const uploadBlobInfo = (blobInfo, handler, openNotification) => {
19841
        uploadStatus.markPending(blobInfo.blobUri());
19842
        return new Promise(resolve => {
19843
          let notification;
19844
          let progress;
19845
          try {
19846
            const closeNotification = () => {
19847
              if (notification) {
19848
                notification.close();
19849
                progress = noop;
19850
              }
19851
            };
19852
            const success = url => {
19853
              closeNotification();
19854
              uploadStatus.markUploaded(blobInfo.blobUri(), url);
19855
              resolvePending(blobInfo.blobUri(), handlerSuccess(blobInfo, url));
19856
              resolve(handlerSuccess(blobInfo, url));
19857
            };
19858
            const failure = error => {
19859
              closeNotification();
19860
              uploadStatus.removeFailed(blobInfo.blobUri());
19861
              resolvePending(blobInfo.blobUri(), handlerFailure(blobInfo, error));
19862
              resolve(handlerFailure(blobInfo, error));
19863
            };
19864
            progress = percent => {
19865
              if (percent < 0 || percent > 100) {
19866
                return;
19867
              }
19868
              Optional.from(notification).orThunk(() => Optional.from(openNotification).map(apply$1)).each(n => {
19869
                notification = n;
19870
                n.progressBar.value(percent);
19871
              });
19872
            };
19873
            handler(blobInfo, progress).then(success, err => {
19874
              failure(isString(err) ? { message: err } : err);
19875
            });
19876
          } catch (ex) {
19877
            resolve(handlerFailure(blobInfo, ex));
19878
          }
19879
        });
19880
      };
19881
      const isDefaultHandler = handler => handler === defaultHandler;
19882
      const pendingUploadBlobInfo = blobInfo => {
19883
        const blobUri = blobInfo.blobUri();
19884
        return new Promise(resolve => {
19885
          pendingPromises[blobUri] = pendingPromises[blobUri] || [];
19886
          pendingPromises[blobUri].push(resolve);
19887
        });
19888
      };
19889
      const uploadBlobs = (blobInfos, openNotification) => {
19890
        blobInfos = Tools.grep(blobInfos, blobInfo => !uploadStatus.isUploaded(blobInfo.blobUri()));
19891
        return Promise.all(Tools.map(blobInfos, blobInfo => uploadStatus.isPending(blobInfo.blobUri()) ? pendingUploadBlobInfo(blobInfo) : uploadBlobInfo(blobInfo, uploadHandler, openNotification)));
19892
      };
19893
      const upload = (blobInfos, openNotification) => !settings.url && isDefaultHandler(uploadHandler) ? noUpload() : uploadBlobs(blobInfos, openNotification);
19894
      return { upload };
19895
    };
19896
 
19897
    const openNotification = editor => () => editor.notificationManager.open({
19898
      text: editor.translate('Image uploading...'),
19899
      type: 'info',
19900
      timeout: -1,
19901
      progressBar: true
19902
    });
19903
    const createUploader = (editor, uploadStatus) => Uploader(uploadStatus, {
19904
      url: getImageUploadUrl(editor),
19905
      basePath: getImageUploadBasePath(editor),
19906
      credentials: getImagesUploadCredentials(editor),
19907
      handler: getImagesUploadHandler(editor)
19908
    });
19909
    const ImageUploader = editor => {
19910
      const uploadStatus = UploadStatus();
19911
      const uploader = createUploader(editor, uploadStatus);
19912
      return { upload: (blobInfos, showNotification = true) => uploader.upload(blobInfos, showNotification ? openNotification(editor) : undefined) };
19913
    };
19914
 
19915
    const isEmptyForPadding = (editor, element) => editor.dom.isEmpty(element.dom) && isNonNullable(editor.schema.getTextBlockElements()[name(element)]);
19916
    const addPaddingToEmpty = editor => element => {
19917
      if (isEmptyForPadding(editor, element)) {
19918
        append$1(element, SugarElement.fromHtml('<br data-mce-bogus="1" />'));
19919
      }
19920
    };
19921
    const EditorUpload = editor => {
19922
      const blobCache = BlobCache();
19923
      let uploader, imageScanner;
19924
      const uploadStatus = UploadStatus();
19925
      const urlFilters = [];
19926
      const aliveGuard = callback => {
19927
        return result => {
19928
          if (editor.selection) {
19929
            return callback(result);
19930
          }
19931
          return [];
19932
        };
19933
      };
19934
      const cacheInvalidator = url => url + (url.indexOf('?') === -1 ? '?' : '&') + new Date().getTime();
19935
      const replaceString = (content, search, replace) => {
19936
        let index = 0;
19937
        do {
19938
          index = content.indexOf(search, index);
19939
          if (index !== -1) {
19940
            content = content.substring(0, index) + replace + content.substr(index + search.length);
19941
            index += replace.length - search.length + 1;
19942
          }
19943
        } while (index !== -1);
19944
        return content;
19945
      };
19946
      const replaceImageUrl = (content, targetUrl, replacementUrl) => {
19947
        const replacementString = `src="${ replacementUrl }"${ replacementUrl === Env.transparentSrc ? ' data-mce-placeholder="1"' : '' }`;
19948
        content = replaceString(content, `src="${ targetUrl }"`, replacementString);
19949
        content = replaceString(content, 'data-mce-src="' + targetUrl + '"', 'data-mce-src="' + replacementUrl + '"');
19950
        return content;
19951
      };
19952
      const replaceUrlInUndoStack = (targetUrl, replacementUrl) => {
19953
        each$e(editor.undoManager.data, level => {
19954
          if (level.type === 'fragmented') {
19955
            level.fragments = map$3(level.fragments, fragment => replaceImageUrl(fragment, targetUrl, replacementUrl));
19956
          } else {
19957
            level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
19958
          }
19959
        });
19960
      };
19961
      const replaceImageUriInView = (image, resultUri) => {
19962
        const src = editor.convertURL(resultUri, 'src');
19963
        replaceUrlInUndoStack(image.src, resultUri);
19964
        setAll$1(SugarElement.fromDom(image), {
19965
          'src': shouldReuseFileName(editor) ? cacheInvalidator(resultUri) : resultUri,
19966
          'data-mce-src': src
19967
        });
19968
      };
19969
      const uploadImages = () => {
19970
        if (!uploader) {
19971
          uploader = createUploader(editor, uploadStatus);
19972
        }
19973
        return scanForImages().then(aliveGuard(imageInfos => {
19974
          const blobInfos = map$3(imageInfos, imageInfo => imageInfo.blobInfo);
19975
          return uploader.upload(blobInfos, openNotification(editor)).then(aliveGuard(result => {
19976
            const imagesToRemove = [];
19977
            let shouldDispatchChange = false;
19978
            const filteredResult = map$3(result, (uploadInfo, index) => {
19979
              const {blobInfo, image} = imageInfos[index];
19980
              let removed = false;
19981
              if (uploadInfo.status && shouldReplaceBlobUris(editor)) {
19982
                if (uploadInfo.url && !contains$1(image.src, uploadInfo.url)) {
19983
                  shouldDispatchChange = true;
19984
                }
19985
                blobCache.removeByUri(image.src);
19986
                if (isRtc(editor)) ; else {
19987
                  replaceImageUriInView(image, uploadInfo.url);
19988
                }
19989
              } else if (uploadInfo.error) {
19990
                if (uploadInfo.error.remove) {
19991
                  replaceUrlInUndoStack(image.src, Env.transparentSrc);
19992
                  imagesToRemove.push(image);
19993
                  removed = true;
19994
                }
19995
                uploadError(editor, uploadInfo.error.message);
19996
              }
19997
              return {
19998
                element: image,
19999
                status: uploadInfo.status,
20000
                uploadUri: uploadInfo.url,
20001
                blobInfo,
20002
                removed
20003
              };
20004
            });
20005
            if (imagesToRemove.length > 0 && !isRtc(editor)) {
20006
              editor.undoManager.transact(() => {
20007
                each$e(fromDom$1(imagesToRemove), sugarElement => {
20008
                  const parentOpt = parent(sugarElement);
20009
                  remove$5(sugarElement);
20010
                  parentOpt.each(addPaddingToEmpty(editor));
20011
                  blobCache.removeByUri(sugarElement.dom.src);
20012
                });
20013
              });
20014
            } else if (shouldDispatchChange) {
20015
              editor.undoManager.dispatchChange();
20016
            }
20017
            return filteredResult;
20018
          }));
20019
        }));
20020
      };
20021
      const uploadImagesAuto = () => isAutomaticUploadsEnabled(editor) ? uploadImages() : Promise.resolve([]);
20022
      const isValidDataUriImage = imgElm => forall(urlFilters, filter => filter(imgElm));
20023
      const addFilter = filter => {
20024
        urlFilters.push(filter);
20025
      };
20026
      const scanForImages = () => {
20027
        if (!imageScanner) {
20028
          imageScanner = ImageScanner(uploadStatus, blobCache);
20029
        }
20030
        return imageScanner.findAll(editor.getBody(), isValidDataUriImage).then(aliveGuard(result => {
20031
          const filteredResult = filter$5(result, resultItem => {
20032
            if (isString(resultItem)) {
20033
              displayError(editor, resultItem);
20034
              return false;
20035
            } else if (resultItem.uriType === 'blob') {
20036
              return false;
20037
            } else {
20038
              return true;
20039
            }
20040
          });
20041
          if (isRtc(editor)) ; else {
20042
            each$e(filteredResult, resultItem => {
20043
              replaceUrlInUndoStack(resultItem.image.src, resultItem.blobInfo.blobUri());
20044
              resultItem.image.src = resultItem.blobInfo.blobUri();
20045
              resultItem.image.removeAttribute('data-mce-src');
20046
            });
20047
          }
20048
          return filteredResult;
20049
        }));
20050
      };
20051
      const destroy = () => {
20052
        blobCache.destroy();
20053
        uploadStatus.destroy();
20054
        imageScanner = uploader = null;
20055
      };
20056
      const replaceBlobUris = content => {
20057
        return content.replace(/src="(blob:[^"]+)"/g, (match, blobUri) => {
20058
          const resultUri = uploadStatus.getResultUri(blobUri);
20059
          if (resultUri) {
20060
            return 'src="' + resultUri + '"';
20061
          }
20062
          let blobInfo = blobCache.getByUri(blobUri);
20063
          if (!blobInfo) {
20064
            blobInfo = foldl(editor.editorManager.get(), (result, editor) => {
20065
              return result || editor.editorUpload && editor.editorUpload.blobCache.getByUri(blobUri);
20066
            }, undefined);
20067
          }
20068
          if (blobInfo) {
20069
            const blob = blobInfo.blob();
20070
            return 'src="data:' + blob.type + ';base64,' + blobInfo.base64() + '"';
20071
          }
20072
          return match;
20073
        });
20074
      };
20075
      editor.on('SetContent', () => {
20076
        if (isAutomaticUploadsEnabled(editor)) {
20077
          uploadImagesAuto();
20078
        } else {
20079
          scanForImages();
20080
        }
20081
      });
20082
      editor.on('RawSaveContent', e => {
20083
        e.content = replaceBlobUris(e.content);
20084
      });
20085
      editor.on('GetContent', e => {
20086
        if (e.source_view || e.format === 'raw' || e.format === 'tree') {
20087
          return;
20088
        }
20089
        e.content = replaceBlobUris(e.content);
20090
      });
20091
      editor.on('PostRender', () => {
20092
        editor.parser.addNodeFilter('img', images => {
20093
          each$e(images, img => {
20094
            const src = img.attr('src');
20095
            if (!src || blobCache.getByUri(src)) {
20096
              return;
20097
            }
20098
            const resultUri = uploadStatus.getResultUri(src);
20099
            if (resultUri) {
20100
              img.attr('src', resultUri);
20101
            }
20102
          });
20103
        });
20104
      });
20105
      return {
20106
        blobCache,
20107
        addFilter,
20108
        uploadImages,
20109
        uploadImagesAuto,
20110
        scanForImages,
20111
        destroy
20112
      };
20113
    };
20114
 
20115
    const get$1 = editor => {
20116
      const dom = editor.dom;
20117
      const schemaType = editor.schema.type;
20118
      const formats = {
20119
        valigntop: [{
20120
            selector: 'td,th',
20121
            styles: { verticalAlign: 'top' }
20122
          }],
20123
        valignmiddle: [{
20124
            selector: 'td,th',
20125
            styles: { verticalAlign: 'middle' }
20126
          }],
20127
        valignbottom: [{
20128
            selector: 'td,th',
20129
            styles: { verticalAlign: 'bottom' }
20130
          }],
20131
        alignleft: [
20132
          {
20133
            selector: 'figure.image',
20134
            collapsed: false,
20135
            classes: 'align-left',
20136
            ceFalseOverride: true,
20137
            preview: 'font-family font-size'
20138
          },
20139
          {
20140
            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
20141
            styles: { textAlign: 'left' },
20142
            inherit: false,
20143
            preview: false
20144
          },
20145
          {
20146
            selector: 'img,audio,video',
20147
            collapsed: false,
20148
            styles: { float: 'left' },
20149
            preview: 'font-family font-size'
20150
          },
20151
          {
20152
            selector: 'table',
20153
            collapsed: false,
20154
            styles: {
20155
              marginLeft: '0px',
20156
              marginRight: 'auto'
20157
            },
20158
            onformat: table => {
20159
              dom.setStyle(table, 'float', null);
20160
            },
20161
            preview: 'font-family font-size'
20162
          },
20163
          {
20164
            selector: '.mce-preview-object,[data-ephox-embed-iri]',
20165
            ceFalseOverride: true,
20166
            styles: { float: 'left' }
20167
          }
20168
        ],
20169
        aligncenter: [
20170
          {
20171
            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
20172
            styles: { textAlign: 'center' },
20173
            inherit: false,
20174
            preview: 'font-family font-size'
20175
          },
20176
          {
20177
            selector: 'figure.image',
20178
            collapsed: false,
20179
            classes: 'align-center',
20180
            ceFalseOverride: true,
20181
            preview: 'font-family font-size'
20182
          },
20183
          {
20184
            selector: 'img,audio,video',
20185
            collapsed: false,
20186
            styles: {
20187
              display: 'block',
20188
              marginLeft: 'auto',
20189
              marginRight: 'auto'
20190
            },
20191
            preview: false
20192
          },
20193
          {
20194
            selector: 'table',
20195
            collapsed: false,
20196
            styles: {
20197
              marginLeft: 'auto',
20198
              marginRight: 'auto'
20199
            },
20200
            preview: 'font-family font-size'
20201
          },
20202
          {
20203
            selector: '.mce-preview-object',
20204
            ceFalseOverride: true,
20205
            styles: {
20206
              display: 'table',
20207
              marginLeft: 'auto',
20208
              marginRight: 'auto'
20209
            },
20210
            preview: false
20211
          },
20212
          {
20213
            selector: '[data-ephox-embed-iri]',
20214
            ceFalseOverride: true,
20215
            styles: {
20216
              marginLeft: 'auto',
20217
              marginRight: 'auto'
20218
            },
20219
            preview: false
20220
          }
20221
        ],
20222
        alignright: [
20223
          {
20224
            selector: 'figure.image',
20225
            collapsed: false,
20226
            classes: 'align-right',
20227
            ceFalseOverride: true,
20228
            preview: 'font-family font-size'
20229
          },
20230
          {
20231
            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
20232
            styles: { textAlign: 'right' },
20233
            inherit: false,
20234
            preview: 'font-family font-size'
20235
          },
20236
          {
20237
            selector: 'img,audio,video',
20238
            collapsed: false,
20239
            styles: { float: 'right' },
20240
            preview: 'font-family font-size'
20241
          },
20242
          {
20243
            selector: 'table',
20244
            collapsed: false,
20245
            styles: {
20246
              marginRight: '0px',
20247
              marginLeft: 'auto'
20248
            },
20249
            onformat: table => {
20250
              dom.setStyle(table, 'float', null);
20251
            },
20252
            preview: 'font-family font-size'
20253
          },
20254
          {
20255
            selector: '.mce-preview-object,[data-ephox-embed-iri]',
20256
            ceFalseOverride: true,
20257
            styles: { float: 'right' },
20258
            preview: false
20259
          }
20260
        ],
20261
        alignjustify: [{
20262
            selector: 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre',
20263
            styles: { textAlign: 'justify' },
20264
            inherit: false,
20265
            preview: 'font-family font-size'
20266
          }],
20267
        bold: [
20268
          {
20269
            inline: 'strong',
20270
            remove: 'all',
20271
            preserve_attributes: [
20272
              'class',
20273
              'style'
20274
            ]
20275
          },
20276
          {
20277
            inline: 'span',
20278
            styles: { fontWeight: 'bold' }
20279
          },
20280
          {
20281
            inline: 'b',
20282
            remove: 'all',
20283
            preserve_attributes: [
20284
              'class',
20285
              'style'
20286
            ]
20287
          }
20288
        ],
20289
        italic: [
20290
          {
20291
            inline: 'em',
20292
            remove: 'all',
20293
            preserve_attributes: [
20294
              'class',
20295
              'style'
20296
            ]
20297
          },
20298
          {
20299
            inline: 'span',
20300
            styles: { fontStyle: 'italic' }
20301
          },
20302
          {
20303
            inline: 'i',
20304
            remove: 'all',
20305
            preserve_attributes: [
20306
              'class',
20307
              'style'
20308
            ]
20309
          }
20310
        ],
20311
        underline: [
20312
          {
20313
            inline: 'span',
20314
            styles: { textDecoration: 'underline' },
20315
            exact: true
20316
          },
20317
          {
20318
            inline: 'u',
20319
            remove: 'all',
20320
            preserve_attributes: [
20321
              'class',
20322
              'style'
20323
            ]
20324
          }
20325
        ],
20326
        strikethrough: (() => {
20327
          const span = {
20328
            inline: 'span',
20329
            styles: { textDecoration: 'line-through' },
20330
            exact: true
20331
          };
20332
          const strike = {
20333
            inline: 'strike',
20334
            remove: 'all',
20335
            preserve_attributes: [
20336
              'class',
20337
              'style'
20338
            ]
20339
          };
20340
          const s = {
20341
            inline: 's',
20342
            remove: 'all',
20343
            preserve_attributes: [
20344
              'class',
20345
              'style'
20346
            ]
20347
          };
20348
          return schemaType !== 'html4' ? [
20349
            s,
20350
            span,
20351
            strike
20352
          ] : [
20353
            span,
20354
            s,
20355
            strike
20356
          ];
20357
        })(),
20358
        forecolor: {
20359
          inline: 'span',
20360
          styles: { color: '%value' },
20361
          links: true,
20362
          remove_similar: true,
20363
          clear_child_styles: true
20364
        },
20365
        hilitecolor: {
20366
          inline: 'span',
20367
          styles: { backgroundColor: '%value' },
20368
          links: true,
20369
          remove_similar: true,
20370
          clear_child_styles: true
20371
        },
20372
        fontname: {
20373
          inline: 'span',
20374
          toggle: false,
20375
          styles: { fontFamily: '%value' },
20376
          clear_child_styles: true
20377
        },
20378
        fontsize: {
20379
          inline: 'span',
20380
          toggle: false,
20381
          styles: { fontSize: '%value' },
20382
          clear_child_styles: true
20383
        },
20384
        lineheight: {
20385
          selector: 'h1,h2,h3,h4,h5,h6,p,li,td,th,div',
20386
          styles: { lineHeight: '%value' }
20387
        },
20388
        fontsize_class: {
20389
          inline: 'span',
20390
          attributes: { class: '%value' }
20391
        },
20392
        blockquote: {
20393
          block: 'blockquote',
20394
          wrapper: true,
20395
          remove: 'all'
20396
        },
20397
        subscript: { inline: 'sub' },
20398
        superscript: { inline: 'sup' },
20399
        code: { inline: 'code' },
20400
        link: {
20401
          inline: 'a',
20402
          selector: 'a',
20403
          remove: 'all',
20404
          split: true,
20405
          deep: true,
20406
          onmatch: (node, _fmt, _itemName) => {
20407
            return isElement$6(node) && node.hasAttribute('href');
20408
          },
20409
          onformat: (elm, _fmt, vars) => {
20410
            Tools.each(vars, (value, key) => {
20411
              dom.setAttrib(elm, key, value);
20412
            });
20413
          }
20414
        },
20415
        lang: {
20416
          inline: 'span',
20417
          clear_child_styles: true,
20418
          remove_similar: true,
20419
          attributes: {
20420
            'lang': '%value',
20421
            'data-mce-lang': vars => {
20422
              var _a;
20423
              return (_a = vars === null || vars === void 0 ? void 0 : vars.customValue) !== null && _a !== void 0 ? _a : null;
20424
            }
20425
          }
20426
        },
20427
        removeformat: [
20428
          {
20429
            selector: 'b,strong,em,i,font,u,strike,s,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins,small',
20430
            remove: 'all',
20431
            split: true,
20432
            expand: false,
20433
            block_expand: true,
20434
            deep: true
20435
          },
20436
          {
20437
            selector: 'span',
20438
            attributes: [
20439
              'style',
20440
              'class'
20441
            ],
20442
            remove: 'empty',
20443
            split: true,
20444
            expand: false,
20445
            deep: true
20446
          },
20447
          {
20448
            selector: '*',
20449
            attributes: [
20450
              'style',
20451
              'class'
20452
            ],
20453
            split: false,
20454
            expand: false,
20455
            deep: true
20456
          }
20457
        ]
20458
      };
20459
      Tools.each('p h1 h2 h3 h4 h5 h6 div address pre dt dd samp'.split(/\s/), name => {
20460
        formats[name] = {
20461
          block: name,
20462
          remove: 'all'
20463
        };
20464
      });
20465
      return formats;
20466
    };
20467
 
20468
    const genericBase = {
20469
      remove_similar: true,
20470
      inherit: false
20471
    };
20472
    const cellBase = {
20473
      selector: 'td,th',
20474
      ...genericBase
20475
    };
20476
    const cellFormats = {
20477
      tablecellbackgroundcolor: {
20478
        styles: { backgroundColor: '%value' },
20479
        ...cellBase
20480
      },
20481
      tablecellverticalalign: {
20482
        styles: { 'vertical-align': '%value' },
20483
        ...cellBase
20484
      },
20485
      tablecellbordercolor: {
20486
        styles: { borderColor: '%value' },
20487
        ...cellBase
20488
      },
20489
      tablecellclass: {
20490
        classes: ['%value'],
20491
        ...cellBase
20492
      },
20493
      tableclass: {
20494
        selector: 'table',
20495
        classes: ['%value'],
20496
        ...genericBase
20497
      },
20498
      tablecellborderstyle: {
20499
        styles: { borderStyle: '%value' },
20500
        ...cellBase
20501
      },
20502
      tablecellborderwidth: {
20503
        styles: { borderWidth: '%value' },
20504
        ...cellBase
20505
      }
20506
    };
20507
    const get = constant(cellFormats);
20508
 
20509
    const FormatRegistry = editor => {
20510
      const formats = {};
20511
      const get$2 = name => isNonNullable(name) ? formats[name] : formats;
20512
      const has = name => has$2(formats, name);
20513
      const register = (name, format) => {
20514
        if (name) {
20515
          if (!isString(name)) {
20516
            each$d(name, (format, name) => {
20517
              register(name, format);
20518
            });
20519
          } else {
20520
            if (!isArray$1(format)) {
20521
              format = [format];
20522
            }
20523
            each$e(format, format => {
20524
              if (isUndefined(format.deep)) {
20525
                format.deep = !isSelectorFormat(format);
20526
              }
20527
              if (isUndefined(format.split)) {
20528
                format.split = !isSelectorFormat(format) || isInlineFormat(format);
20529
              }
20530
              if (isUndefined(format.remove) && isSelectorFormat(format) && !isInlineFormat(format)) {
20531
                format.remove = 'none';
20532
              }
20533
              if (isSelectorFormat(format) && isInlineFormat(format)) {
20534
                format.mixed = true;
20535
                format.block_expand = true;
20536
              }
20537
              if (isString(format.classes)) {
20538
                format.classes = format.classes.split(/\s+/);
20539
              }
20540
            });
20541
            formats[name] = format;
20542
          }
20543
        }
20544
      };
20545
      const unregister = name => {
20546
        if (name && formats[name]) {
20547
          delete formats[name];
20548
        }
20549
        return formats;
20550
      };
20551
      register(get$1(editor));
20552
      register(get());
20553
      register(getFormats(editor));
20554
      return {
20555
        get: get$2,
20556
        has,
20557
        register,
20558
        unregister
20559
      };
20560
    };
20561
 
20562
    const each$3 = Tools.each;
20563
    const dom = DOMUtils.DOM;
20564
    const isPreviewItem = item => isNonNullable(item) && isObject(item);
20565
    const parsedSelectorToHtml = (ancestry, editor) => {
20566
      const schema = editor && editor.schema || Schema({});
20567
      const decorate = (elm, item) => {
20568
        if (item.classes.length > 0) {
20569
          dom.addClass(elm, item.classes.join(' '));
20570
        }
20571
        dom.setAttribs(elm, item.attrs);
20572
      };
20573
      const createElement = sItem => {
20574
        const item = isString(sItem) ? {
20575
          name: sItem,
20576
          classes: [],
20577
          attrs: {}
20578
        } : sItem;
20579
        const elm = dom.create(item.name);
20580
        decorate(elm, item);
20581
        return elm;
20582
      };
20583
      const getRequiredParent = (elm, candidate) => {
20584
        const elmRule = schema.getElementRule(elm.nodeName.toLowerCase());
20585
        const parentsRequired = elmRule === null || elmRule === void 0 ? void 0 : elmRule.parentsRequired;
20586
        if (parentsRequired && parentsRequired.length) {
20587
          return candidate && contains$2(parentsRequired, candidate) ? candidate : parentsRequired[0];
20588
        } else {
20589
          return false;
20590
        }
20591
      };
20592
      const wrapInHtml = (elm, ancestors, siblings) => {
20593
        let parentCandidate;
20594
        const ancestor = ancestors[0];
20595
        const ancestorName = isPreviewItem(ancestor) ? ancestor.name : undefined;
20596
        const parentRequired = getRequiredParent(elm, ancestorName);
20597
        if (parentRequired) {
20598
          if (ancestorName === parentRequired) {
20599
            parentCandidate = ancestor;
20600
            ancestors = ancestors.slice(1);
20601
          } else {
20602
            parentCandidate = parentRequired;
20603
          }
20604
        } else if (ancestor) {
20605
          parentCandidate = ancestor;
20606
          ancestors = ancestors.slice(1);
20607
        } else if (!siblings) {
20608
          return elm;
20609
        }
20610
        const parent = parentCandidate ? createElement(parentCandidate) : dom.create('div');
20611
        parent.appendChild(elm);
20612
        if (siblings) {
20613
          Tools.each(siblings, sibling => {
20614
            const siblingElm = createElement(sibling);
20615
            parent.insertBefore(siblingElm, elm);
20616
          });
20617
        }
20618
        const parentSiblings = isPreviewItem(parentCandidate) ? parentCandidate.siblings : undefined;
20619
        return wrapInHtml(parent, ancestors, parentSiblings);
20620
      };
20621
      const fragment = dom.create('div');
20622
      if (ancestry.length > 0) {
20623
        const item = ancestry[0];
20624
        const elm = createElement(item);
20625
        const siblings = isPreviewItem(item) ? item.siblings : undefined;
20626
        fragment.appendChild(wrapInHtml(elm, ancestry.slice(1), siblings));
20627
      }
20628
      return fragment;
20629
    };
20630
    const parseSelectorItem = item => {
20631
      item = Tools.trim(item);
20632
      let tagName = 'div';
20633
      const obj = {
20634
        name: tagName,
20635
        classes: [],
20636
        attrs: {},
20637
        selector: item
20638
      };
20639
      if (item !== '*') {
20640
        tagName = item.replace(/(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g, ($0, $1, $2, $3, $4) => {
20641
          switch ($1) {
20642
          case '#':
20643
            obj.attrs.id = $2;
20644
            break;
20645
          case '.':
20646
            obj.classes.push($2);
20647
            break;
20648
          case ':':
20649
            if (Tools.inArray('checked disabled enabled read-only required'.split(' '), $2) !== -1) {
20650
              obj.attrs[$2] = $2;
20651
            }
20652
            break;
20653
          }
20654
          if ($3 === '[') {
20655
            const m = $4.match(/([\w\-]+)(?:\=\"([^\"]+))?/);
20656
            if (m) {
20657
              obj.attrs[m[1]] = m[2];
20658
            }
20659
          }
20660
          return '';
20661
        });
20662
      }
20663
      obj.name = tagName || 'div';
20664
      return obj;
20665
    };
20666
    const parseSelector = selector => {
20667
      if (!isString(selector)) {
20668
        return [];
20669
      }
20670
      selector = selector.split(/\s*,\s*/)[0];
20671
      selector = selector.replace(/\s*(~\+|~|\+|>)\s*/g, '$1');
20672
      return Tools.map(selector.split(/(?:>|\s+(?![^\[\]]+\]))/), item => {
20673
        const siblings = Tools.map(item.split(/(?:~\+|~|\+)/), parseSelectorItem);
20674
        const obj = siblings.pop();
20675
        if (siblings.length) {
20676
          obj.siblings = siblings;
20677
        }
20678
        return obj;
20679
      }).reverse();
20680
    };
20681
    const getCssText = (editor, format) => {
20682
      let previewCss = '';
20683
      let previewStyles = getPreviewStyles(editor);
20684
      if (previewStyles === '') {
20685
        return '';
20686
      }
20687
      const removeVars = val => {
20688
        return isString(val) ? val.replace(/%(\w+)/g, '') : '';
20689
      };
20690
      const getComputedStyle = (name, elm) => {
20691
        return dom.getStyle(elm !== null && elm !== void 0 ? elm : editor.getBody(), name, true);
20692
      };
20693
      if (isString(format)) {
20694
        const formats = editor.formatter.get(format);
20695
        if (!formats) {
20696
          return '';
20697
        }
20698
        format = formats[0];
20699
      }
20700
      if ('preview' in format) {
20701
        const preview = format.preview;
20702
        if (preview === false) {
20703
          return '';
20704
        } else {
20705
          previewStyles = preview || previewStyles;
20706
        }
20707
      }
20708
      let name = format.block || format.inline || 'span';
20709
      let previewFrag;
20710
      const items = parseSelector(format.selector);
20711
      if (items.length > 0) {
20712
        if (!items[0].name) {
20713
          items[0].name = name;
20714
        }
20715
        name = format.selector;
20716
        previewFrag = parsedSelectorToHtml(items, editor);
20717
      } else {
20718
        previewFrag = parsedSelectorToHtml([name], editor);
20719
      }
20720
      const previewElm = dom.select(name, previewFrag)[0] || previewFrag.firstChild;
20721
      each$3(format.styles, (value, name) => {
20722
        const newValue = removeVars(value);
20723
        if (newValue) {
20724
          dom.setStyle(previewElm, name, newValue);
20725
        }
20726
      });
20727
      each$3(format.attributes, (value, name) => {
20728
        const newValue = removeVars(value);
20729
        if (newValue) {
20730
          dom.setAttrib(previewElm, name, newValue);
20731
        }
20732
      });
20733
      each$3(format.classes, value => {
20734
        const newValue = removeVars(value);
20735
        if (!dom.hasClass(previewElm, newValue)) {
20736
          dom.addClass(previewElm, newValue);
20737
        }
20738
      });
20739
      editor.dispatch('PreviewFormats');
20740
      dom.setStyles(previewFrag, {
20741
        position: 'absolute',
20742
        left: -65535
20743
      });
20744
      editor.getBody().appendChild(previewFrag);
20745
      const rawParentFontSize = getComputedStyle('fontSize');
20746
      const parentFontSize = /px$/.test(rawParentFontSize) ? parseInt(rawParentFontSize, 10) : 0;
20747
      each$3(previewStyles.split(' '), name => {
20748
        let value = getComputedStyle(name, previewElm);
20749
        if (name === 'background-color' && /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)) {
20750
          value = getComputedStyle(name);
20751
          if (rgbaToHexString(value).toLowerCase() === '#ffffff') {
20752
            return;
20753
          }
20754
        }
20755
        if (name === 'color') {
20756
          if (rgbaToHexString(value).toLowerCase() === '#000000') {
20757
            return;
20758
          }
20759
        }
20760
        if (name === 'font-size') {
20761
          if (/em|%$/.test(value)) {
20762
            if (parentFontSize === 0) {
20763
              return;
20764
            }
20765
            const numValue = parseFloat(value) / (/%$/.test(value) ? 100 : 1);
20766
            value = numValue * parentFontSize + 'px';
20767
          }
20768
        }
20769
        if (name === 'border' && value) {
20770
          previewCss += 'padding:0 2px;';
20771
        }
20772
        previewCss += name + ':' + value + ';';
20773
      });
20774
      editor.dispatch('AfterPreviewFormats');
20775
      dom.remove(previewFrag);
20776
      return previewCss;
20777
    };
20778
 
20779
    const setup$s = editor => {
20780
      editor.addShortcut('meta+b', '', 'Bold');
20781
      editor.addShortcut('meta+i', '', 'Italic');
20782
      editor.addShortcut('meta+u', '', 'Underline');
20783
      for (let i = 1; i <= 6; i++) {
20784
        editor.addShortcut('access+' + i, '', [
20785
          'FormatBlock',
20786
          false,
20787
          'h' + i
20788
        ]);
20789
      }
20790
      editor.addShortcut('access+7', '', [
20791
        'FormatBlock',
20792
        false,
20793
        'p'
20794
      ]);
20795
      editor.addShortcut('access+8', '', [
20796
        'FormatBlock',
20797
        false,
20798
        'div'
20799
      ]);
20800
      editor.addShortcut('access+9', '', [
20801
        'FormatBlock',
20802
        false,
20803
        'address'
20804
      ]);
20805
    };
20806
 
20807
    const Formatter = editor => {
20808
      const formats = FormatRegistry(editor);
20809
      const formatChangeState = Cell({});
20810
      setup$s(editor);
20811
      setup$v(editor);
20812
      if (!isRtc(editor)) {
20813
        setup$u(formatChangeState, editor);
20814
      }
20815
      return {
20816
        get: formats.get,
20817
        has: formats.has,
20818
        register: formats.register,
20819
        unregister: formats.unregister,
20820
        apply: (name, vars, node) => {
20821
          applyFormat(editor, name, vars, node);
20822
        },
20823
        remove: (name, vars, node, similar) => {
20824
          removeFormat(editor, name, vars, node, similar);
20825
        },
20826
        toggle: (name, vars, node) => {
20827
          toggleFormat(editor, name, vars, node);
20828
        },
20829
        match: (name, vars, node, similar) => matchFormat(editor, name, vars, node, similar),
20830
        closest: names => closestFormat(editor, names),
20831
        matchAll: (names, vars) => matchAllFormats(editor, names, vars),
20832
        matchNode: (node, name, vars, similar) => matchNodeFormat(editor, node, name, vars, similar),
20833
        canApply: name => canApplyFormat(editor, name),
20834
        formatChanged: (formats, callback, similar, vars) => formatChanged(editor, formatChangeState, formats, callback, similar, vars),
20835
        getCssText: curry(getCssText, editor)
20836
      };
20837
    };
20838
 
20839
    const shouldIgnoreCommand = cmd => {
20840
      switch (cmd.toLowerCase()) {
20841
      case 'undo':
20842
      case 'redo':
20843
      case 'mcefocus':
20844
        return true;
20845
      default:
20846
        return false;
20847
      }
20848
    };
20849
    const registerEvents = (editor, undoManager, locks) => {
20850
      const isFirstTypedCharacter = Cell(false);
20851
      const addNonTypingUndoLevel = e => {
20852
        setTyping(undoManager, false, locks);
20853
        undoManager.add({}, e);
20854
      };
20855
      editor.on('init', () => {
20856
        undoManager.add();
20857
      });
20858
      editor.on('BeforeExecCommand', e => {
20859
        const cmd = e.command;
20860
        if (!shouldIgnoreCommand(cmd)) {
20861
          endTyping(undoManager, locks);
20862
          undoManager.beforeChange();
20863
        }
20864
      });
20865
      editor.on('ExecCommand', e => {
20866
        const cmd = e.command;
20867
        if (!shouldIgnoreCommand(cmd)) {
20868
          addNonTypingUndoLevel(e);
20869
        }
20870
      });
20871
      editor.on('ObjectResizeStart cut', () => {
20872
        undoManager.beforeChange();
20873
      });
20874
      editor.on('SaveContent ObjectResized blur', addNonTypingUndoLevel);
20875
      editor.on('dragend', addNonTypingUndoLevel);
20876
      editor.on('keyup', e => {
20877
        const keyCode = e.keyCode;
20878
        if (e.isDefaultPrevented()) {
20879
          return;
20880
        }
20881
        const isMeta = Env.os.isMacOS() && e.key === 'Meta';
20882
        if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45 || e.ctrlKey || isMeta) {
20883
          addNonTypingUndoLevel();
20884
          editor.nodeChanged();
20885
        }
20886
        if (keyCode === 46 || keyCode === 8) {
20887
          editor.nodeChanged();
20888
        }
20889
        if (isFirstTypedCharacter.get() && undoManager.typing && !isEq$1(createFromEditor(editor), undoManager.data[0])) {
20890
          if (!editor.isDirty()) {
20891
            editor.setDirty(true);
20892
          }
20893
          editor.dispatch('TypingUndo');
20894
          isFirstTypedCharacter.set(false);
20895
          editor.nodeChanged();
20896
        }
20897
      });
20898
      editor.on('keydown', e => {
20899
        const keyCode = e.keyCode;
20900
        if (e.isDefaultPrevented()) {
20901
          return;
20902
        }
20903
        if (keyCode >= 33 && keyCode <= 36 || keyCode >= 37 && keyCode <= 40 || keyCode === 45) {
20904
          if (undoManager.typing) {
20905
            addNonTypingUndoLevel(e);
20906
          }
20907
          return;
20908
        }
20909
        const modKey = e.ctrlKey && !e.altKey || e.metaKey;
20910
        if ((keyCode < 16 || keyCode > 20) && keyCode !== 224 && keyCode !== 91 && !undoManager.typing && !modKey) {
20911
          undoManager.beforeChange();
20912
          setTyping(undoManager, true, locks);
20913
          undoManager.add({}, e);
20914
          isFirstTypedCharacter.set(true);
20915
          return;
20916
        }
20917
        const hasOnlyMetaOrCtrlModifier = Env.os.isMacOS() ? e.metaKey : e.ctrlKey && !e.altKey;
20918
        if (hasOnlyMetaOrCtrlModifier) {
20919
          undoManager.beforeChange();
20920
        }
20921
      });
20922
      editor.on('mousedown', e => {
20923
        if (undoManager.typing) {
20924
          addNonTypingUndoLevel(e);
20925
        }
20926
      });
20927
      const isInsertReplacementText = event => event.inputType === 'insertReplacementText';
20928
      const isInsertTextDataNull = event => event.inputType === 'insertText' && event.data === null;
20929
      const isInsertFromPasteOrDrop = event => event.inputType === 'insertFromPaste' || event.inputType === 'insertFromDrop';
20930
      editor.on('input', e => {
20931
        if (e.inputType && (isInsertReplacementText(e) || isInsertTextDataNull(e) || isInsertFromPasteOrDrop(e))) {
20932
          addNonTypingUndoLevel(e);
20933
        }
20934
      });
20935
      editor.on('AddUndo Undo Redo ClearUndos', e => {
20936
        if (!e.isDefaultPrevented()) {
20937
          editor.nodeChanged();
20938
        }
20939
      });
20940
    };
20941
    const addKeyboardShortcuts = editor => {
20942
      editor.addShortcut('meta+z', '', 'Undo');
20943
      editor.addShortcut('meta+y,meta+shift+z', '', 'Redo');
20944
    };
20945
 
20946
    const UndoManager = editor => {
20947
      const beforeBookmark = value$2();
20948
      const locks = Cell(0);
20949
      const index = Cell(0);
20950
      const undoManager = {
20951
        data: [],
20952
        typing: false,
20953
        beforeChange: () => {
20954
          beforeChange(editor, locks, beforeBookmark);
20955
        },
20956
        add: (level, event) => {
20957
          return addUndoLevel(editor, undoManager, index, locks, beforeBookmark, level, event);
20958
        },
20959
        dispatchChange: () => {
20960
          editor.setDirty(true);
20961
          const level = createFromEditor(editor);
20962
          level.bookmark = getUndoBookmark(editor.selection);
20963
          editor.dispatch('change', {
20964
            level,
20965
            lastLevel: get$b(undoManager.data, index.get()).getOrUndefined()
20966
          });
20967
        },
20968
        undo: () => {
20969
          return undo(editor, undoManager, locks, index);
20970
        },
20971
        redo: () => {
20972
          return redo(editor, index, undoManager.data);
20973
        },
20974
        clear: () => {
20975
          clear(editor, undoManager, index);
20976
        },
20977
        reset: () => {
20978
          reset(editor, undoManager);
20979
        },
20980
        hasUndo: () => {
20981
          return hasUndo(editor, undoManager, index);
20982
        },
20983
        hasRedo: () => {
20984
          return hasRedo(editor, undoManager, index);
20985
        },
20986
        transact: callback => {
20987
          return transact(editor, undoManager, locks, callback);
20988
        },
20989
        ignore: callback => {
20990
          ignore(editor, locks, callback);
20991
        },
20992
        extra: (callback1, callback2) => {
20993
          extra(editor, undoManager, index, callback1, callback2);
20994
        }
20995
      };
20996
      if (!isRtc(editor)) {
20997
        registerEvents(editor, undoManager, locks);
20998
      }
20999
      addKeyboardShortcuts(editor);
21000
      return undoManager;
21001
    };
21002
 
21003
    const nonTypingKeycodes = [
21004
      9,
21005
      27,
21006
      VK.HOME,
21007
      VK.END,
21008
      19,
21009
      20,
21010
      44,
21011
      144,
21012
      145,
21013
      33,
21014
      34,
21015
      45,
21016
      16,
21017
      17,
21018
      18,
21019
      91,
21020
      92,
21021
      93,
21022
      VK.DOWN,
21023
      VK.UP,
21024
      VK.LEFT,
21025
      VK.RIGHT
21026
    ].concat(Env.browser.isFirefox() ? [224] : []);
21027
    const placeholderAttr = 'data-mce-placeholder';
21028
    const isKeyboardEvent = e => e.type === 'keydown' || e.type === 'keyup';
21029
    const isDeleteEvent = e => {
21030
      const keyCode = e.keyCode;
21031
      return keyCode === VK.BACKSPACE || keyCode === VK.DELETE;
21032
    };
21033
    const isNonTypingKeyboardEvent = e => {
21034
      if (isKeyboardEvent(e)) {
21035
        const keyCode = e.keyCode;
21036
        return !isDeleteEvent(e) && (VK.metaKeyPressed(e) || e.altKey || keyCode >= 112 && keyCode <= 123 || contains$2(nonTypingKeycodes, keyCode));
21037
      } else {
21038
        return false;
21039
      }
21040
    };
21041
    const isTypingKeyboardEvent = e => isKeyboardEvent(e) && !(isDeleteEvent(e) || e.type === 'keyup' && e.keyCode === 229);
21042
    const isVisuallyEmpty = (dom, rootElm, forcedRootBlock) => {
21043
      if (isEmpty$2(SugarElement.fromDom(rootElm), false)) {
21044
        const firstElement = rootElm.firstElementChild;
21045
        if (!firstElement) {
21046
          return true;
21047
        } else if (dom.getStyle(rootElm.firstElementChild, 'padding-left') || dom.getStyle(rootElm.firstElementChild, 'padding-right')) {
21048
          return false;
21049
        } else {
21050
          return forcedRootBlock === firstElement.nodeName.toLowerCase();
21051
        }
21052
      } else {
21053
        return false;
21054
      }
21055
    };
21056
    const setup$r = editor => {
21057
      var _a;
21058
      const dom = editor.dom;
21059
      const rootBlock = getForcedRootBlock(editor);
21060
      const placeholder = (_a = getPlaceholder(editor)) !== null && _a !== void 0 ? _a : '';
21061
      const updatePlaceholder = (e, initial) => {
21062
        if (isNonTypingKeyboardEvent(e)) {
21063
          return;
21064
        }
21065
        const body = editor.getBody();
21066
        const showPlaceholder = isTypingKeyboardEvent(e) ? false : isVisuallyEmpty(dom, body, rootBlock);
21067
        const isPlaceholderShown = dom.getAttrib(body, placeholderAttr) !== '';
21068
        if (isPlaceholderShown !== showPlaceholder || initial) {
21069
          dom.setAttrib(body, placeholderAttr, showPlaceholder ? placeholder : null);
21070
          dom.setAttrib(body, 'aria-placeholder', showPlaceholder ? placeholder : null);
21071
          firePlaceholderToggle(editor, showPlaceholder);
21072
          editor.on(showPlaceholder ? 'keydown' : 'keyup', updatePlaceholder);
21073
          editor.off(showPlaceholder ? 'keyup' : 'keydown', updatePlaceholder);
21074
        }
21075
      };
21076
      if (isNotEmpty(placeholder)) {
21077
        editor.on('init', e => {
21078
          updatePlaceholder(e, true);
21079
          editor.on('change SetContent ExecCommand', updatePlaceholder);
21080
          editor.on('paste', e => Delay.setEditorTimeout(editor, () => updatePlaceholder(e)));
21081
        });
21082
      }
21083
    };
21084
 
21085
    const blockPosition = (block, position) => ({
21086
      block,
21087
      position
21088
    });
21089
    const blockBoundary = (from, to) => ({
21090
      from,
21091
      to
21092
    });
21093
    const getBlockPosition = (rootNode, pos) => {
21094
      const rootElm = SugarElement.fromDom(rootNode);
21095
      const containerElm = SugarElement.fromDom(pos.container());
21096
      return getParentBlock$2(rootElm, containerElm).map(block => blockPosition(block, pos));
21097
    };
21098
    const isDifferentBlocks = blockBoundary => !eq(blockBoundary.from.block, blockBoundary.to.block);
21099
    const getClosestHost = (root, scope) => {
21100
      const isRoot = node => eq(node, root);
21101
      const isHost = node => isTableCell$2(node) || isContentEditableTrue$3(node.dom);
21102
      return closest$4(scope, isHost, isRoot).filter(isElement$7).getOr(root);
21103
    };
21104
    const hasSameHost = (rootNode, blockBoundary) => {
21105
      const root = SugarElement.fromDom(rootNode);
21106
      return eq(getClosestHost(root, blockBoundary.from.block), getClosestHost(root, blockBoundary.to.block));
21107
    };
21108
    const isEditable$1 = blockBoundary => isContentEditableFalse$b(blockBoundary.from.block.dom) === false && isContentEditableFalse$b(blockBoundary.to.block.dom) === false;
21109
    const hasValidBlocks = blockBoundary => {
21110
      const isValidBlock = block => isTextBlock$2(block) || hasBlockAttr(block.dom);
21111
      return isValidBlock(blockBoundary.from.block) && isValidBlock(blockBoundary.to.block);
21112
    };
21113
    const skipLastBr = (rootNode, forward, blockPosition) => {
21114
      if (isBr$6(blockPosition.position.getNode()) && !isEmpty$2(blockPosition.block)) {
21115
        return positionIn(false, blockPosition.block.dom).bind(lastPositionInBlock => {
21116
          if (lastPositionInBlock.isEqual(blockPosition.position)) {
21117
            return fromPosition(forward, rootNode, lastPositionInBlock).bind(to => getBlockPosition(rootNode, to));
21118
          } else {
21119
            return Optional.some(blockPosition);
21120
          }
21121
        }).getOr(blockPosition);
21122
      } else {
21123
        return blockPosition;
21124
      }
21125
    };
21126
    const readFromRange = (rootNode, forward, rng) => {
21127
      const fromBlockPos = getBlockPosition(rootNode, CaretPosition.fromRangeStart(rng));
21128
      const toBlockPos = fromBlockPos.bind(blockPos => fromPosition(forward, rootNode, blockPos.position).bind(to => getBlockPosition(rootNode, to).map(blockPos => skipLastBr(rootNode, forward, blockPos))));
21129
      return lift2(fromBlockPos, toBlockPos, blockBoundary).filter(blockBoundary => isDifferentBlocks(blockBoundary) && hasSameHost(rootNode, blockBoundary) && isEditable$1(blockBoundary) && hasValidBlocks(blockBoundary));
21130
    };
21131
    const read$1 = (rootNode, forward, rng) => rng.collapsed ? readFromRange(rootNode, forward, rng) : Optional.none();
21132
 
21133
    const getChildrenUntilBlockBoundary = (block, schema) => {
21134
      const children = children$1(block);
21135
      return findIndex$2(children, el => schema.isBlock(name(el))).fold(constant(children), index => children.slice(0, index));
21136
    };
21137
    const extractChildren = (block, schema) => {
21138
      const children = getChildrenUntilBlockBoundary(block, schema);
21139
      each$e(children, remove$5);
21140
      return children;
21141
    };
21142
    const removeEmptyRoot = (rootNode, block) => {
21143
      const parents = parentsAndSelf(block, rootNode);
21144
      return find$2(parents.reverse(), element => isEmpty$2(element)).each(remove$5);
21145
    };
21146
    const isEmptyBefore = el => filter$5(prevSiblings(el), el => !isEmpty$2(el)).length === 0;
21147
    const nestedBlockMerge = (rootNode, fromBlock, toBlock, schema, insertionPoint) => {
21148
      if (isEmpty$2(toBlock)) {
21149
        fillWithPaddingBr(toBlock);
21150
        return firstPositionIn(toBlock.dom);
21151
      }
21152
      if (isEmptyBefore(insertionPoint) && isEmpty$2(fromBlock)) {
21153
        before$3(insertionPoint, SugarElement.fromTag('br'));
21154
      }
21155
      const position = prevPosition(toBlock.dom, CaretPosition.before(insertionPoint.dom));
21156
      each$e(extractChildren(fromBlock, schema), child => {
21157
        before$3(insertionPoint, child);
21158
      });
21159
      removeEmptyRoot(rootNode, fromBlock);
21160
      return position;
21161
    };
21162
    const isInline = (schema, node) => schema.isInline(name(node));
21163
    const sidelongBlockMerge = (rootNode, fromBlock, toBlock, schema) => {
21164
      if (isEmpty$2(toBlock)) {
21165
        if (isEmpty$2(fromBlock)) {
21166
          const getInlineToBlockDescendants = el => {
21167
            const helper = (node, elements) => firstChild(node).fold(() => elements, child => isInline(schema, child) ? helper(child, elements.concat(shallow$1(child))) : elements);
21168
            return helper(el, []);
21169
          };
21170
          const newFromBlockDescendants = foldr(getInlineToBlockDescendants(toBlock), (element, descendant) => {
21171
            wrap$2(element, descendant);
21172
            return descendant;
21173
          }, createPaddingBr());
21174
          empty(fromBlock);
21175
          append$1(fromBlock, newFromBlockDescendants);
21176
        }
21177
        remove$5(toBlock);
21178
        return firstPositionIn(fromBlock.dom);
21179
      }
21180
      const position = lastPositionIn(toBlock.dom);
21181
      each$e(extractChildren(fromBlock, schema), child => {
21182
        append$1(toBlock, child);
21183
      });
21184
      removeEmptyRoot(rootNode, fromBlock);
21185
      return position;
21186
    };
21187
    const findInsertionPoint = (toBlock, block) => {
21188
      const parentsAndSelf$1 = parentsAndSelf(block, toBlock);
21189
      return Optional.from(parentsAndSelf$1[parentsAndSelf$1.length - 1]);
21190
    };
21191
    const getInsertionPoint = (fromBlock, toBlock) => contains(toBlock, fromBlock) ? findInsertionPoint(toBlock, fromBlock) : Optional.none();
21192
    const trimBr = (first, block) => {
21193
      positionIn(first, block.dom).bind(position => Optional.from(position.getNode())).map(SugarElement.fromDom).filter(isBr$5).each(remove$5);
21194
    };
21195
    const mergeBlockInto = (rootNode, fromBlock, toBlock, schema) => {
21196
      trimBr(true, fromBlock);
21197
      trimBr(false, toBlock);
21198
      return getInsertionPoint(fromBlock, toBlock).fold(curry(sidelongBlockMerge, rootNode, fromBlock, toBlock, schema), curry(nestedBlockMerge, rootNode, fromBlock, toBlock, schema));
21199
    };
21200
    const mergeBlocks = (rootNode, forward, block1, block2, schema) => forward ? mergeBlockInto(rootNode, block2, block1, schema) : mergeBlockInto(rootNode, block1, block2, schema);
21201
 
21202
    const backspaceDelete$9 = (editor, forward) => {
21203
      const rootNode = SugarElement.fromDom(editor.getBody());
21204
      const position = read$1(rootNode.dom, forward, editor.selection.getRng()).map(blockBoundary => () => {
21205
        mergeBlocks(rootNode, forward, blockBoundary.from.block, blockBoundary.to.block, editor.schema).each(pos => {
21206
          editor.selection.setRng(pos.toRange());
21207
        });
21208
      });
21209
      return position;
21210
    };
21211
 
21212
    const deleteRangeMergeBlocks = (rootNode, selection, schema) => {
21213
      const rng = selection.getRng();
21214
      return lift2(getParentBlock$2(rootNode, SugarElement.fromDom(rng.startContainer)), getParentBlock$2(rootNode, SugarElement.fromDom(rng.endContainer)), (block1, block2) => {
21215
        if (!eq(block1, block2)) {
21216
          return Optional.some(() => {
21217
            rng.deleteContents();
21218
            mergeBlocks(rootNode, true, block1, block2, schema).each(pos => {
21219
              selection.setRng(pos.toRange());
21220
            });
21221
          });
21222
        } else {
21223
          return Optional.none();
21224
        }
21225
      }).getOr(Optional.none());
21226
    };
21227
    const isRawNodeInTable = (root, rawNode) => {
21228
      const node = SugarElement.fromDom(rawNode);
21229
      const isRoot = curry(eq, root);
21230
      return ancestor$4(node, isTableCell$2, isRoot).isSome();
21231
    };
21232
    const isSelectionInTable = (root, rng) => isRawNodeInTable(root, rng.startContainer) || isRawNodeInTable(root, rng.endContainer);
21233
    const isEverythingSelected = (root, rng) => {
21234
      const noPrevious = prevPosition(root.dom, CaretPosition.fromRangeStart(rng)).isNone();
21235
      const noNext = nextPosition(root.dom, CaretPosition.fromRangeEnd(rng)).isNone();
21236
      return !isSelectionInTable(root, rng) && noPrevious && noNext;
21237
    };
21238
    const emptyEditor = editor => {
21239
      return Optional.some(() => {
21240
        editor.setContent('');
21241
        editor.selection.setCursorLocation();
21242
      });
21243
    };
21244
    const deleteRange$2 = editor => {
21245
      const rootNode = SugarElement.fromDom(editor.getBody());
21246
      const rng = editor.selection.getRng();
21247
      return isEverythingSelected(rootNode, rng) ? emptyEditor(editor) : deleteRangeMergeBlocks(rootNode, editor.selection, editor.schema);
21248
    };
21249
    const backspaceDelete$8 = (editor, _forward) => editor.selection.isCollapsed() ? Optional.none() : deleteRange$2(editor);
21250
 
21251
    const showCaret = (direction, editor, node, before, scrollIntoView) => Optional.from(editor._selectionOverrides.showCaret(direction, node, before, scrollIntoView));
21252
    const getNodeRange = node => {
21253
      const rng = node.ownerDocument.createRange();
21254
      rng.selectNode(node);
21255
      return rng;
21256
    };
21257
    const selectNode = (editor, node) => {
21258
      const e = editor.dispatch('BeforeObjectSelected', { target: node });
21259
      if (e.isDefaultPrevented()) {
21260
        return Optional.none();
21261
      }
21262
      return Optional.some(getNodeRange(node));
21263
    };
21264
    const renderCaretAtRange = (editor, range, scrollIntoView) => {
21265
      const normalizedRange = normalizeRange(1, editor.getBody(), range);
21266
      const caretPosition = CaretPosition.fromRangeStart(normalizedRange);
21267
      const caretPositionNode = caretPosition.getNode();
21268
      if (isInlineFakeCaretTarget(caretPositionNode)) {
21269
        return showCaret(1, editor, caretPositionNode, !caretPosition.isAtEnd(), false);
21270
      }
21271
      const caretPositionBeforeNode = caretPosition.getNode(true);
21272
      if (isInlineFakeCaretTarget(caretPositionBeforeNode)) {
21273
        return showCaret(1, editor, caretPositionBeforeNode, false, false);
21274
      }
21275
      const ceRoot = getContentEditableRoot$1(editor.dom.getRoot(), caretPosition.getNode());
21276
      if (isInlineFakeCaretTarget(ceRoot)) {
21277
        return showCaret(1, editor, ceRoot, false, scrollIntoView);
21278
      }
21279
      return Optional.none();
21280
    };
21281
    const renderRangeCaret = (editor, range, scrollIntoView) => range.collapsed ? renderCaretAtRange(editor, range, scrollIntoView).getOr(range) : range;
21282
 
21283
    const isBeforeBoundary = pos => isBeforeContentEditableFalse(pos) || isBeforeMedia(pos);
21284
    const isAfterBoundary = pos => isAfterContentEditableFalse(pos) || isAfterMedia(pos);
21285
    const trimEmptyTextNode = (dom, node) => {
21286
      if (isText$a(node) && node.data.length === 0) {
21287
        dom.remove(node);
21288
      }
21289
    };
21290
    const deleteContentAndShowCaret = (editor, range, node, direction, forward, peekCaretPosition) => {
21291
      showCaret(direction, editor, peekCaretPosition.getNode(!forward), forward, true).each(caretRange => {
21292
        if (range.collapsed) {
21293
          const deleteRange = range.cloneRange();
21294
          if (forward) {
21295
            deleteRange.setEnd(caretRange.startContainer, caretRange.startOffset);
21296
          } else {
21297
            deleteRange.setStart(caretRange.endContainer, caretRange.endOffset);
21298
          }
21299
          deleteRange.deleteContents();
21300
        } else {
21301
          range.deleteContents();
21302
        }
21303
        editor.selection.setRng(caretRange);
21304
      });
21305
      trimEmptyTextNode(editor.dom, node);
21306
    };
21307
    const deleteBoundaryText = (editor, forward) => {
21308
      const range = editor.selection.getRng();
21309
      if (!isText$a(range.commonAncestorContainer)) {
21310
        return Optional.none();
21311
      }
21312
      const direction = forward ? HDirection.Forwards : HDirection.Backwards;
21313
      const caretWalker = CaretWalker(editor.getBody());
21314
      const getNextPosFn = curry(getVisualCaretPosition, forward ? caretWalker.next : caretWalker.prev);
21315
      const isBeforeFn = forward ? isBeforeBoundary : isAfterBoundary;
21316
      const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
21317
      const nextCaretPosition = getNextPosFn(caretPosition);
21318
      const normalizedNextCaretPosition = nextCaretPosition ? normalizePosition(forward, nextCaretPosition) : nextCaretPosition;
21319
      if (!normalizedNextCaretPosition || !isMoveInsideSameBlock(caretPosition, normalizedNextCaretPosition)) {
21320
        return Optional.none();
21321
      } else if (isBeforeFn(normalizedNextCaretPosition)) {
21322
        return Optional.some(() => deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, normalizedNextCaretPosition));
21323
      }
21324
      const peekCaretPosition = getNextPosFn(normalizedNextCaretPosition);
21325
      if (peekCaretPosition && isBeforeFn(peekCaretPosition)) {
21326
        if (isMoveInsideSameBlock(normalizedNextCaretPosition, peekCaretPosition)) {
21327
          return Optional.some(() => deleteContentAndShowCaret(editor, range, caretPosition.getNode(), direction, forward, peekCaretPosition));
21328
        }
21329
      }
21330
      return Optional.none();
21331
    };
21332
    const backspaceDelete$7 = (editor, forward) => deleteBoundaryText(editor, forward);
21333
 
21334
    const getEdgeCefPosition = (editor, atStart) => {
21335
      const root = editor.getBody();
21336
      return atStart ? firstPositionIn(root).filter(isBeforeContentEditableFalse) : lastPositionIn(root).filter(isAfterContentEditableFalse);
21337
    };
21338
    const isCefAtEdgeSelected = editor => {
21339
      const rng = editor.selection.getRng();
21340
      return !rng.collapsed && (getEdgeCefPosition(editor, true).exists(pos => pos.isEqual(CaretPosition.fromRangeStart(rng))) || getEdgeCefPosition(editor, false).exists(pos => pos.isEqual(CaretPosition.fromRangeEnd(rng))));
21341
    };
21342
 
21343
    const isCompoundElement = node => isNonNullable(node) && (isTableCell$2(SugarElement.fromDom(node)) || isListItem$1(SugarElement.fromDom(node)));
21344
    const DeleteAction = Adt.generate([
21345
      { remove: ['element'] },
21346
      { moveToElement: ['element'] },
21347
      { moveToPosition: ['position'] }
21348
    ]);
21349
    const isAtContentEditableBlockCaret = (forward, from) => {
21350
      const elm = from.getNode(!forward);
21351
      const caretLocation = forward ? 'after' : 'before';
21352
      return isElement$6(elm) && elm.getAttribute('data-mce-caret') === caretLocation;
21353
    };
21354
    const isDeleteFromCefDifferentBlocks = (root, forward, from, to, schema) => {
21355
      const inSameBlock = elm => schema.isInline(elm.nodeName.toLowerCase()) && !isInSameBlock(from, to, root);
21356
      return getRelativeCefElm(!forward, from).fold(() => getRelativeCefElm(forward, to).fold(never, inSameBlock), inSameBlock);
21357
    };
21358
    const deleteEmptyBlockOrMoveToCef = (root, forward, from, to) => {
21359
      const toCefElm = to.getNode(!forward);
21360
      return getParentBlock$2(SugarElement.fromDom(root), SugarElement.fromDom(from.getNode())).map(blockElm => isEmpty$2(blockElm) ? DeleteAction.remove(blockElm.dom) : DeleteAction.moveToElement(toCefElm)).orThunk(() => Optional.some(DeleteAction.moveToElement(toCefElm)));
21361
    };
21362
    const findCefPosition = (root, forward, from, schema) => fromPosition(forward, root, from).bind(to => {
21363
      if (isCompoundElement(to.getNode())) {
21364
        return Optional.none();
21365
      } else if (isDeleteFromCefDifferentBlocks(root, forward, from, to, schema)) {
21366
        return Optional.none();
21367
      } else if (forward && isContentEditableFalse$b(to.getNode())) {
21368
        return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
21369
      } else if (!forward && isContentEditableFalse$b(to.getNode(true))) {
21370
        return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
21371
      } else if (forward && isAfterContentEditableFalse(from)) {
21372
        return Optional.some(DeleteAction.moveToPosition(to));
21373
      } else if (!forward && isBeforeContentEditableFalse(from)) {
21374
        return Optional.some(DeleteAction.moveToPosition(to));
21375
      } else {
21376
        return Optional.none();
21377
      }
21378
    });
21379
    const getContentEditableBlockAction = (forward, elm) => {
21380
      if (isNullable(elm)) {
21381
        return Optional.none();
21382
      } else if (forward && isContentEditableFalse$b(elm.nextSibling)) {
21383
        return Optional.some(DeleteAction.moveToElement(elm.nextSibling));
21384
      } else if (!forward && isContentEditableFalse$b(elm.previousSibling)) {
21385
        return Optional.some(DeleteAction.moveToElement(elm.previousSibling));
21386
      } else {
21387
        return Optional.none();
21388
      }
21389
    };
21390
    const skipMoveToActionFromInlineCefToContent = (root, from, deleteAction) => deleteAction.fold(elm => Optional.some(DeleteAction.remove(elm)), elm => Optional.some(DeleteAction.moveToElement(elm)), to => {
21391
      if (isInSameBlock(from, to, root)) {
21392
        return Optional.none();
21393
      } else {
21394
        return Optional.some(DeleteAction.moveToPosition(to));
21395
      }
21396
    });
21397
    const getContentEditableAction = (root, forward, from, schema) => {
21398
      if (isAtContentEditableBlockCaret(forward, from)) {
21399
        return getContentEditableBlockAction(forward, from.getNode(!forward)).orThunk(() => findCefPosition(root, forward, from, schema));
21400
      } else {
21401
        return findCefPosition(root, forward, from, schema).bind(deleteAction => skipMoveToActionFromInlineCefToContent(root, from, deleteAction));
21402
      }
21403
    };
21404
    const read = (root, forward, rng, schema) => {
21405
      const normalizedRange = normalizeRange(forward ? 1 : -1, root, rng);
21406
      const from = CaretPosition.fromRangeStart(normalizedRange);
21407
      const rootElement = SugarElement.fromDom(root);
21408
      if (!forward && isAfterContentEditableFalse(from)) {
21409
        return Optional.some(DeleteAction.remove(from.getNode(true)));
21410
      } else if (forward && isBeforeContentEditableFalse(from)) {
21411
        return Optional.some(DeleteAction.remove(from.getNode()));
21412
      } else if (!forward && isBeforeContentEditableFalse(from) && isAfterBr(rootElement, from, schema)) {
21413
        return findPreviousBr(rootElement, from, schema).map(br => DeleteAction.remove(br.getNode()));
21414
      } else if (forward && isAfterContentEditableFalse(from) && isBeforeBr$1(rootElement, from, schema)) {
21415
        return findNextBr(rootElement, from, schema).map(br => DeleteAction.remove(br.getNode()));
21416
      } else {
21417
        return getContentEditableAction(root, forward, from, schema);
21418
      }
21419
    };
21420
 
21421
    const deleteElement$1 = (editor, forward) => element => {
21422
      editor._selectionOverrides.hideFakeCaret();
21423
      deleteElement$2(editor, forward, SugarElement.fromDom(element));
21424
      return true;
21425
    };
21426
    const moveToElement = (editor, forward) => element => {
21427
      const pos = forward ? CaretPosition.before(element) : CaretPosition.after(element);
21428
      editor.selection.setRng(pos.toRange());
21429
      return true;
21430
    };
21431
    const moveToPosition = editor => pos => {
21432
      editor.selection.setRng(pos.toRange());
21433
      return true;
21434
    };
21435
    const getAncestorCe = (editor, node) => Optional.from(getContentEditableRoot$1(editor.getBody(), node));
21436
    const backspaceDeleteCaret = (editor, forward) => {
21437
      const selectedNode = editor.selection.getNode();
21438
      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));
21439
    };
21440
    const deleteOffscreenSelection = rootElement => {
21441
      each$e(descendants(rootElement, '.mce-offscreen-selection'), remove$5);
21442
    };
21443
    const backspaceDeleteRange = (editor, forward) => {
21444
      const selectedNode = editor.selection.getNode();
21445
      if (isContentEditableFalse$b(selectedNode) && !isTableCell$3(selectedNode)) {
21446
        const hasCefAncestor = getAncestorCe(editor, selectedNode.parentNode).filter(isContentEditableFalse$b);
21447
        return hasCefAncestor.fold(() => Optional.some(() => {
21448
          deleteOffscreenSelection(SugarElement.fromDom(editor.getBody()));
21449
          deleteElement$2(editor, forward, SugarElement.fromDom(editor.selection.getNode()));
21450
          paddEmptyBody(editor);
21451
        }), () => Optional.some(noop));
21452
      }
21453
      if (isCefAtEdgeSelected(editor)) {
21454
        return Optional.some(() => {
21455
          deleteRangeContents(editor, editor.selection.getRng(), SugarElement.fromDom(editor.getBody()));
21456
        });
21457
      }
21458
      return Optional.none();
21459
    };
21460
    const paddEmptyElement = editor => {
21461
      const dom = editor.dom, selection = editor.selection;
21462
      const ceRoot = getContentEditableRoot$1(editor.getBody(), selection.getNode());
21463
      if (isContentEditableTrue$3(ceRoot) && dom.isBlock(ceRoot) && dom.isEmpty(ceRoot)) {
21464
        const br = dom.create('br', { 'data-mce-bogus': '1' });
21465
        dom.setHTML(ceRoot, '');
21466
        ceRoot.appendChild(br);
21467
        selection.setRng(CaretPosition.before(br).toRange());
21468
      }
21469
      return true;
21470
    };
21471
    const backspaceDelete$6 = (editor, forward) => {
21472
      if (editor.selection.isCollapsed()) {
21473
        return backspaceDeleteCaret(editor, forward);
21474
      } else {
21475
        return backspaceDeleteRange(editor, forward);
21476
      }
21477
    };
21478
 
21479
    const deleteCaret$2 = (editor, forward) => {
21480
      const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
21481
      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));
21482
    };
21483
    const backspaceDelete$5 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret$2(editor, forward) : Optional.none();
21484
 
21485
    const isText$2 = isText$a;
21486
    const startsWithCaretContainer = node => isText$2(node) && node.data[0] === ZWSP$1;
21487
    const endsWithCaretContainer = node => isText$2(node) && node.data[node.data.length - 1] === ZWSP$1;
21488
    const createZwsp = node => {
21489
      var _a;
21490
      const doc = (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
21491
      return doc.createTextNode(ZWSP$1);
21492
    };
21493
    const insertBefore$1 = node => {
21494
      var _a;
21495
      if (isText$2(node.previousSibling)) {
21496
        if (endsWithCaretContainer(node.previousSibling)) {
21497
          return node.previousSibling;
21498
        } else {
21499
          node.previousSibling.appendData(ZWSP$1);
21500
          return node.previousSibling;
21501
        }
21502
      } else if (isText$2(node)) {
21503
        if (startsWithCaretContainer(node)) {
21504
          return node;
21505
        } else {
21506
          node.insertData(0, ZWSP$1);
21507
          return node;
21508
        }
21509
      } else {
21510
        const newNode = createZwsp(node);
21511
        (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newNode, node);
21512
        return newNode;
21513
      }
21514
    };
21515
    const insertAfter$1 = node => {
21516
      var _a, _b;
21517
      if (isText$2(node.nextSibling)) {
21518
        if (startsWithCaretContainer(node.nextSibling)) {
21519
          return node.nextSibling;
21520
        } else {
21521
          node.nextSibling.insertData(0, ZWSP$1);
21522
          return node.nextSibling;
21523
        }
21524
      } else if (isText$2(node)) {
21525
        if (endsWithCaretContainer(node)) {
21526
          return node;
21527
        } else {
21528
          node.appendData(ZWSP$1);
21529
          return node;
21530
        }
21531
      } else {
21532
        const newNode = createZwsp(node);
21533
        if (node.nextSibling) {
21534
          (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(newNode, node.nextSibling);
21535
        } else {
21536
          (_b = node.parentNode) === null || _b === void 0 ? void 0 : _b.appendChild(newNode);
21537
        }
21538
        return newNode;
21539
      }
21540
    };
21541
    const insertInline = (before, node) => before ? insertBefore$1(node) : insertAfter$1(node);
21542
    const insertInlineBefore = curry(insertInline, true);
21543
    const insertInlineAfter = curry(insertInline, false);
21544
 
21545
    const insertInlinePos = (pos, before) => {
21546
      if (isText$a(pos.container())) {
21547
        return insertInline(before, pos.container());
21548
      } else {
21549
        return insertInline(before, pos.getNode());
21550
      }
21551
    };
21552
    const isPosCaretContainer = (pos, caret) => {
21553
      const caretNode = caret.get();
21554
      return caretNode && pos.container() === caretNode && isCaretContainerInline(caretNode);
21555
    };
21556
    const renderCaret = (caret, location) => location.fold(element => {
21557
      remove$3(caret.get());
21558
      const text = insertInlineBefore(element);
21559
      caret.set(text);
21560
      return Optional.some(CaretPosition(text, text.length - 1));
21561
    }, element => firstPositionIn(element).map(pos => {
21562
      if (!isPosCaretContainer(pos, caret)) {
21563
        remove$3(caret.get());
21564
        const text = insertInlinePos(pos, true);
21565
        caret.set(text);
21566
        return CaretPosition(text, 1);
21567
      } else {
21568
        const node = caret.get();
21569
        return CaretPosition(node, 1);
21570
      }
21571
    }), element => lastPositionIn(element).map(pos => {
21572
      if (!isPosCaretContainer(pos, caret)) {
21573
        remove$3(caret.get());
21574
        const text = insertInlinePos(pos, false);
21575
        caret.set(text);
21576
        return CaretPosition(text, text.length - 1);
21577
      } else {
21578
        const node = caret.get();
21579
        return CaretPosition(node, node.length - 1);
21580
      }
21581
    }), element => {
21582
      remove$3(caret.get());
21583
      const text = insertInlineAfter(element);
21584
      caret.set(text);
21585
      return Optional.some(CaretPosition(text, 1));
21586
    });
21587
 
21588
    const evaluateUntil = (fns, args) => {
21589
      for (let i = 0; i < fns.length; i++) {
21590
        const result = fns[i].apply(null, args);
21591
        if (result.isSome()) {
21592
          return result;
21593
        }
21594
      }
21595
      return Optional.none();
21596
    };
21597
 
21598
    const Location = Adt.generate([
21599
      { before: ['element'] },
21600
      { start: ['element'] },
21601
      { end: ['element'] },
21602
      { after: ['element'] }
21603
    ]);
21604
    const rescope$1 = (rootNode, node) => {
21605
      const parentBlock = getParentBlock$3(node, rootNode);
21606
      return parentBlock ? parentBlock : rootNode;
21607
    };
21608
    const before = (isInlineTarget, rootNode, pos) => {
21609
      const nPos = normalizeForwards(pos);
21610
      const scope = rescope$1(rootNode, nPos.container());
21611
      return findRootInline(isInlineTarget, scope, nPos).fold(() => nextPosition(scope, nPos).bind(curry(findRootInline, isInlineTarget, scope)).map(inline => Location.before(inline)), Optional.none);
21612
    };
21613
    const isNotInsideFormatCaretContainer = (rootNode, elm) => getParentCaretContainer(rootNode, elm) === null;
21614
    const findInsideRootInline = (isInlineTarget, rootNode, pos) => findRootInline(isInlineTarget, rootNode, pos).filter(curry(isNotInsideFormatCaretContainer, rootNode));
21615
    const start$1 = (isInlineTarget, rootNode, pos) => {
21616
      const nPos = normalizeBackwards(pos);
21617
      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(inline => {
21618
        const prevPos = prevPosition(inline, nPos);
21619
        return prevPos.isNone() ? Optional.some(Location.start(inline)) : Optional.none();
21620
      });
21621
    };
21622
    const end = (isInlineTarget, rootNode, pos) => {
21623
      const nPos = normalizeForwards(pos);
21624
      return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(inline => {
21625
        const nextPos = nextPosition(inline, nPos);
21626
        return nextPos.isNone() ? Optional.some(Location.end(inline)) : Optional.none();
21627
      });
21628
    };
21629
    const after = (isInlineTarget, rootNode, pos) => {
21630
      const nPos = normalizeBackwards(pos);
21631
      const scope = rescope$1(rootNode, nPos.container());
21632
      return findRootInline(isInlineTarget, scope, nPos).fold(() => prevPosition(scope, nPos).bind(curry(findRootInline, isInlineTarget, scope)).map(inline => Location.after(inline)), Optional.none);
21633
    };
21634
    const isValidLocation = location => !isRtl(getElement(location));
21635
    const readLocation = (isInlineTarget, rootNode, pos) => {
21636
      const location = evaluateUntil([
21637
        before,
21638
        start$1,
21639
        end,
21640
        after
21641
      ], [
21642
        isInlineTarget,
21643
        rootNode,
21644
        pos
21645
      ]);
21646
      return location.filter(isValidLocation);
21647
    };
21648
    const getElement = location => location.fold(identity, identity, identity, identity);
21649
    const getName = location => location.fold(constant('before'), constant('start'), constant('end'), constant('after'));
21650
    const outside = location => location.fold(Location.before, Location.before, Location.after, Location.after);
21651
    const inside = location => location.fold(Location.start, Location.start, Location.end, Location.end);
21652
    const isEq = (location1, location2) => getName(location1) === getName(location2) && getElement(location1) === getElement(location2);
21653
    const betweenInlines = (forward, isInlineTarget, rootNode, from, to, location) => lift2(findRootInline(isInlineTarget, rootNode, from), findRootInline(isInlineTarget, rootNode, to), (fromInline, toInline) => {
21654
      if (fromInline !== toInline && hasSameParentBlock(rootNode, fromInline, toInline)) {
21655
        return Location.after(forward ? fromInline : toInline);
21656
      } else {
21657
        return location;
21658
      }
21659
    }).getOr(location);
21660
    const skipNoMovement = (fromLocation, toLocation) => fromLocation.fold(always, fromLocation => !isEq(fromLocation, toLocation));
21661
    const findLocationTraverse = (forward, isInlineTarget, rootNode, fromLocation, pos) => {
21662
      const from = normalizePosition(forward, pos);
21663
      const to = fromPosition(forward, rootNode, from).map(curry(normalizePosition, forward));
21664
      const location = to.fold(() => fromLocation.map(outside), to => readLocation(isInlineTarget, rootNode, to).map(curry(betweenInlines, forward, isInlineTarget, rootNode, from, to)).filter(curry(skipNoMovement, fromLocation)));
21665
      return location.filter(isValidLocation);
21666
    };
21667
    const findLocationSimple = (forward, location) => {
21668
      if (forward) {
21669
        return location.fold(compose(Optional.some, Location.start), Optional.none, compose(Optional.some, Location.after), Optional.none);
21670
      } else {
21671
        return location.fold(Optional.none, compose(Optional.some, Location.before), Optional.none, compose(Optional.some, Location.end));
21672
      }
21673
    };
21674
    const findLocation$1 = (forward, isInlineTarget, rootNode, pos) => {
21675
      const from = normalizePosition(forward, pos);
21676
      const fromLocation = readLocation(isInlineTarget, rootNode, from);
21677
      return readLocation(isInlineTarget, rootNode, from).bind(curry(findLocationSimple, forward)).orThunk(() => findLocationTraverse(forward, isInlineTarget, rootNode, fromLocation, pos));
21678
    };
21679
 
21680
    const hasSelectionModifyApi = editor => {
21681
      return isFunction(editor.selection.getSel().modify);
21682
    };
21683
    const moveRel = (forward, selection, pos) => {
21684
      const delta = forward ? 1 : -1;
21685
      selection.setRng(CaretPosition(pos.container(), pos.offset() + delta).toRange());
21686
      selection.getSel().modify('move', forward ? 'forward' : 'backward', 'word');
21687
      return true;
21688
    };
21689
    const moveByWord = (forward, editor) => {
21690
      const rng = editor.selection.getRng();
21691
      const pos = forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng);
21692
      if (!hasSelectionModifyApi(editor)) {
21693
        return false;
21694
      } else if (forward && isBeforeInline(pos)) {
21695
        return moveRel(true, editor.selection, pos);
21696
      } else if (!forward && isAfterInline(pos)) {
21697
        return moveRel(false, editor.selection, pos);
21698
      } else {
21699
        return false;
21700
      }
21701
    };
21702
 
21703
    var BreakType;
21704
    (function (BreakType) {
21705
      BreakType[BreakType['Br'] = 0] = 'Br';
21706
      BreakType[BreakType['Block'] = 1] = 'Block';
21707
      BreakType[BreakType['Wrap'] = 2] = 'Wrap';
21708
      BreakType[BreakType['Eol'] = 3] = 'Eol';
21709
    }(BreakType || (BreakType = {})));
21710
    const flip = (direction, positions) => direction === HDirection.Backwards ? reverse(positions) : positions;
21711
    const walk$1 = (direction, caretWalker, pos) => direction === HDirection.Forwards ? caretWalker.next(pos) : caretWalker.prev(pos);
21712
    const getBreakType = (scope, direction, currentPos, nextPos) => {
21713
      if (isBr$6(nextPos.getNode(direction === HDirection.Forwards))) {
21714
        return BreakType.Br;
21715
      } else if (isInSameBlock(currentPos, nextPos) === false) {
21716
        return BreakType.Block;
21717
      } else {
21718
        return BreakType.Wrap;
21719
      }
21720
    };
21721
    const getPositionsUntil = (predicate, direction, scope, start) => {
21722
      const caretWalker = CaretWalker(scope);
21723
      let currentPos = start;
21724
      const positions = [];
21725
      while (currentPos) {
21726
        const nextPos = walk$1(direction, caretWalker, currentPos);
21727
        if (!nextPos) {
21728
          break;
21729
        }
21730
        if (isBr$6(nextPos.getNode(false))) {
21731
          if (direction === HDirection.Forwards) {
21732
            return {
21733
              positions: flip(direction, positions).concat([nextPos]),
21734
              breakType: BreakType.Br,
21735
              breakAt: Optional.some(nextPos)
21736
            };
21737
          } else {
21738
            return {
21739
              positions: flip(direction, positions),
21740
              breakType: BreakType.Br,
21741
              breakAt: Optional.some(nextPos)
21742
            };
21743
          }
21744
        }
21745
        if (!nextPos.isVisible()) {
21746
          currentPos = nextPos;
21747
          continue;
21748
        }
21749
        if (predicate(currentPos, nextPos)) {
21750
          const breakType = getBreakType(scope, direction, currentPos, nextPos);
21751
          return {
21752
            positions: flip(direction, positions),
21753
            breakType,
21754
            breakAt: Optional.some(nextPos)
21755
          };
21756
        }
21757
        positions.push(nextPos);
21758
        currentPos = nextPos;
21759
      }
21760
      return {
21761
        positions: flip(direction, positions),
21762
        breakType: BreakType.Eol,
21763
        breakAt: Optional.none()
21764
      };
21765
    };
21766
    const getAdjacentLinePositions = (direction, getPositionsUntilBreak, scope, start) => getPositionsUntilBreak(scope, start).breakAt.map(pos => {
21767
      const positions = getPositionsUntilBreak(scope, pos).positions;
21768
      return direction === HDirection.Backwards ? positions.concat(pos) : [pos].concat(positions);
21769
    }).getOr([]);
21770
    const findClosestHorizontalPositionFromPoint = (positions, x) => foldl(positions, (acc, newPos) => acc.fold(() => Optional.some(newPos), lastPos => lift2(head(lastPos.getClientRects()), head(newPos.getClientRects()), (lastRect, newRect) => {
21771
      const lastDist = Math.abs(x - lastRect.left);
21772
      const newDist = Math.abs(x - newRect.left);
21773
      return newDist <= lastDist ? newPos : lastPos;
21774
    }).or(acc)), Optional.none());
21775
    const findClosestHorizontalPosition = (positions, pos) => head(pos.getClientRects()).bind(targetRect => findClosestHorizontalPositionFromPoint(positions, targetRect.left));
21776
    const getPositionsUntilPreviousLine = curry(getPositionsUntil, CaretPosition.isAbove, -1);
21777
    const getPositionsUntilNextLine = curry(getPositionsUntil, CaretPosition.isBelow, 1);
21778
    const getPositionsAbove = curry(getAdjacentLinePositions, -1, getPositionsUntilPreviousLine);
21779
    const getPositionsBelow = curry(getAdjacentLinePositions, 1, getPositionsUntilNextLine);
21780
    const isAtFirstLine = (scope, pos) => getPositionsUntilPreviousLine(scope, pos).breakAt.isNone();
21781
    const isAtLastLine = (scope, pos) => getPositionsUntilNextLine(scope, pos).breakAt.isNone();
21782
    const getFirstLinePositions = scope => firstPositionIn(scope).map(pos => [pos].concat(getPositionsUntilNextLine(scope, pos).positions)).getOr([]);
21783
    const getLastLinePositions = scope => lastPositionIn(scope).map(pos => getPositionsUntilPreviousLine(scope, pos).positions.concat(pos)).getOr([]);
21784
    const getClosestPositionAbove = (scope, pos) => findClosestHorizontalPosition(getPositionsAbove(scope, pos), pos);
21785
    const getClosestPositionBelow = (scope, pos) => findClosestHorizontalPosition(getPositionsBelow(scope, pos), pos);
21786
 
21787
    const isContentEditableFalse$4 = isContentEditableFalse$b;
21788
    const distanceToRectLeft$1 = (clientRect, clientX) => Math.abs(clientRect.left - clientX);
21789
    const distanceToRectRight$1 = (clientRect, clientX) => Math.abs(clientRect.right - clientX);
21790
    const isNodeClientRect = rect => hasNonNullableKey(rect, 'node');
21791
    const findClosestClientRect = (clientRects, clientX) => reduce(clientRects, (oldClientRect, clientRect) => {
21792
      const oldDistance = Math.min(distanceToRectLeft$1(oldClientRect, clientX), distanceToRectRight$1(oldClientRect, clientX));
21793
      const newDistance = Math.min(distanceToRectLeft$1(clientRect, clientX), distanceToRectRight$1(clientRect, clientX));
21794
      if (newDistance === oldDistance && isNodeClientRect(clientRect) && isContentEditableFalse$4(clientRect.node)) {
21795
        return clientRect;
21796
      }
21797
      if (newDistance < oldDistance) {
21798
        return clientRect;
21799
      }
21800
      return oldClientRect;
21801
    });
21802
 
21803
    const getNodeClientRects = node => {
21804
      const toArrayWithNode = clientRects => {
21805
        return map$3(clientRects, rect => {
21806
          const clientRect = clone$1(rect);
21807
          clientRect.node = node;
21808
          return clientRect;
21809
        });
21810
      };
21811
      if (isElement$6(node)) {
21812
        return toArrayWithNode(node.getClientRects());
21813
      } else if (isText$a(node)) {
21814
        const rng = node.ownerDocument.createRange();
21815
        rng.setStart(node, 0);
21816
        rng.setEnd(node, node.data.length);
21817
        return toArrayWithNode(rng.getClientRects());
21818
      } else {
21819
        return [];
21820
      }
21821
    };
21822
    const getClientRects = nodes => bind$3(nodes, getNodeClientRects);
21823
 
21824
    var VDirection;
21825
    (function (VDirection) {
21826
      VDirection[VDirection['Up'] = -1] = 'Up';
21827
      VDirection[VDirection['Down'] = 1] = 'Down';
21828
    }(VDirection || (VDirection = {})));
21829
    const findUntil = (direction, root, predicateFn, node) => {
21830
      let currentNode = node;
21831
      while (currentNode = findNode(currentNode, direction, isEditableCaretCandidate$1, root)) {
21832
        if (predicateFn(currentNode)) {
21833
          return;
21834
        }
21835
      }
21836
    };
21837
    const walkUntil = (direction, isAboveFn, isBeflowFn, root, predicateFn, caretPosition) => {
21838
      let line = 0;
21839
      const result = [];
21840
      const add = node => {
21841
        let clientRects = getClientRects([node]);
21842
        if (direction === -1) {
21843
          clientRects = clientRects.reverse();
21844
        }
21845
        for (let i = 0; i < clientRects.length; i++) {
21846
          const clientRect = clientRects[i];
21847
          if (isBeflowFn(clientRect, targetClientRect)) {
21848
            continue;
21849
          }
21850
          if (result.length > 0 && isAboveFn(clientRect, last$2(result))) {
21851
            line++;
21852
          }
21853
          clientRect.line = line;
21854
          if (predicateFn(clientRect)) {
21855
            return true;
21856
          }
21857
          result.push(clientRect);
21858
        }
21859
        return false;
21860
      };
21861
      const targetClientRect = last$2(caretPosition.getClientRects());
21862
      if (!targetClientRect) {
21863
        return result;
21864
      }
21865
      const node = caretPosition.getNode();
21866
      if (node) {
21867
        add(node);
21868
        findUntil(direction, root, add, node);
21869
      }
21870
      return result;
21871
    };
21872
    const aboveLineNumber = (lineNumber, clientRect) => clientRect.line > lineNumber;
21873
    const isLineNumber = (lineNumber, clientRect) => clientRect.line === lineNumber;
21874
    const upUntil = curry(walkUntil, VDirection.Up, isAbove$1, isBelow$1);
21875
    const downUntil = curry(walkUntil, VDirection.Down, isBelow$1, isAbove$1);
21876
    const getLastClientRect = caretPosition => {
21877
      return last$2(caretPosition.getClientRects());
21878
    };
21879
    const positionsUntil = (direction, root, predicateFn, node) => {
21880
      const caretWalker = CaretWalker(root);
21881
      let walkFn;
21882
      let isBelowFn;
21883
      let isAboveFn;
21884
      let caretPosition;
21885
      const result = [];
21886
      let line = 0;
21887
      if (direction === 1) {
21888
        walkFn = caretWalker.next;
21889
        isBelowFn = isBelow$1;
21890
        isAboveFn = isAbove$1;
21891
        caretPosition = CaretPosition.after(node);
21892
      } else {
21893
        walkFn = caretWalker.prev;
21894
        isBelowFn = isAbove$1;
21895
        isAboveFn = isBelow$1;
21896
        caretPosition = CaretPosition.before(node);
21897
      }
21898
      const targetClientRect = getLastClientRect(caretPosition);
21899
      do {
21900
        if (!caretPosition.isVisible()) {
21901
          continue;
21902
        }
21903
        const rect = getLastClientRect(caretPosition);
21904
        if (isAboveFn(rect, targetClientRect)) {
21905
          continue;
21906
        }
21907
        if (result.length > 0 && isBelowFn(rect, last$2(result))) {
21908
          line++;
21909
        }
21910
        const clientRect = clone$1(rect);
21911
        clientRect.position = caretPosition;
21912
        clientRect.line = line;
21913
        if (predicateFn(clientRect)) {
21914
          return result;
21915
        }
21916
        result.push(clientRect);
21917
      } while (caretPosition = walkFn(caretPosition));
21918
      return result;
21919
    };
21920
    const isAboveLine = lineNumber => clientRect => aboveLineNumber(lineNumber, clientRect);
21921
    const isLine = lineNumber => clientRect => isLineNumber(lineNumber, clientRect);
21922
 
21923
    const moveToRange = (editor, rng) => {
21924
      editor.selection.setRng(rng);
21925
      scrollRangeIntoView(editor, editor.selection.getRng());
21926
    };
21927
    const renderRangeCaretOpt = (editor, range, scrollIntoView) => Optional.some(renderRangeCaret(editor, range, scrollIntoView));
21928
    const moveHorizontally = (editor, direction, range, isBefore, isAfter, isElement) => {
21929
      const forwards = direction === HDirection.Forwards;
21930
      const caretWalker = CaretWalker(editor.getBody());
21931
      const getNextPosFn = curry(getVisualCaretPosition, forwards ? caretWalker.next : caretWalker.prev);
21932
      const isBeforeFn = forwards ? isBefore : isAfter;
21933
      if (!range.collapsed) {
21934
        const node = getSelectedNode(range);
21935
        if (isElement(node)) {
21936
          return showCaret(direction, editor, node, direction === HDirection.Backwards, false);
21937
        } else if (isCefAtEdgeSelected(editor)) {
21938
          const newRange = range.cloneRange();
21939
          newRange.collapse(direction === HDirection.Backwards);
21940
          return Optional.from(newRange);
21941
        }
21942
      }
21943
      const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
21944
      if (isBeforeFn(caretPosition)) {
21945
        return selectNode(editor, caretPosition.getNode(!forwards));
21946
      }
21947
      let nextCaretPosition = getNextPosFn(caretPosition);
21948
      const rangeIsInContainerBlock = isRangeInCaretContainerBlock(range);
21949
      if (!nextCaretPosition) {
21950
        return rangeIsInContainerBlock ? Optional.some(range) : Optional.none();
21951
      } else {
21952
        nextCaretPosition = normalizePosition(forwards, nextCaretPosition);
21953
      }
21954
      if (isBeforeFn(nextCaretPosition)) {
21955
        return showCaret(direction, editor, nextCaretPosition.getNode(!forwards), forwards, false);
21956
      }
21957
      const peekCaretPosition = getNextPosFn(nextCaretPosition);
21958
      if (peekCaretPosition && isBeforeFn(peekCaretPosition)) {
21959
        if (isMoveInsideSameBlock(nextCaretPosition, peekCaretPosition)) {
21960
          return showCaret(direction, editor, peekCaretPosition.getNode(!forwards), forwards, false);
21961
        }
21962
      }
21963
      if (rangeIsInContainerBlock) {
21964
        return renderRangeCaretOpt(editor, nextCaretPosition.toRange(), false);
21965
      }
21966
      return Optional.none();
21967
    };
21968
    const moveVertically = (editor, direction, range, isBefore, isAfter, isElement) => {
21969
      const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
21970
      const caretClientRect = last$2(caretPosition.getClientRects());
21971
      const forwards = direction === VDirection.Down;
21972
      const root = editor.getBody();
21973
      if (!caretClientRect) {
21974
        return Optional.none();
21975
      }
21976
      if (isCefAtEdgeSelected(editor)) {
21977
        const caretPosition = forwards ? CaretPosition.fromRangeEnd(range) : CaretPosition.fromRangeStart(range);
21978
        const getClosestFn = !forwards ? getClosestPositionAbove : getClosestPositionBelow;
21979
        return getClosestFn(root, caretPosition).orThunk(() => Optional.from(caretPosition)).map(pos => pos.toRange());
21980
      }
21981
      const walkerFn = forwards ? downUntil : upUntil;
21982
      const linePositions = walkerFn(root, isAboveLine(1), caretPosition);
21983
      const nextLinePositions = filter$5(linePositions, isLine(1));
21984
      const clientX = caretClientRect.left;
21985
      const nextLineRect = findClosestClientRect(nextLinePositions, clientX);
21986
      if (nextLineRect && isElement(nextLineRect.node)) {
21987
        const dist1 = Math.abs(clientX - nextLineRect.left);
21988
        const dist2 = Math.abs(clientX - nextLineRect.right);
21989
        return showCaret(direction, editor, nextLineRect.node, dist1 < dist2, false);
21990
      }
21991
      let currentNode;
21992
      if (isBefore(caretPosition)) {
21993
        currentNode = caretPosition.getNode();
21994
      } else if (isAfter(caretPosition)) {
21995
        currentNode = caretPosition.getNode(true);
21996
      } else {
21997
        currentNode = getSelectedNode(range);
21998
      }
21999
      if (currentNode) {
22000
        const caretPositions = positionsUntil(direction, root, isAboveLine(1), currentNode);
22001
        let closestNextLineRect = findClosestClientRect(filter$5(caretPositions, isLine(1)), clientX);
22002
        if (closestNextLineRect) {
22003
          return renderRangeCaretOpt(editor, closestNextLineRect.position.toRange(), false);
22004
        }
22005
        closestNextLineRect = last$2(filter$5(caretPositions, isLine(0)));
22006
        if (closestNextLineRect) {
22007
          return renderRangeCaretOpt(editor, closestNextLineRect.position.toRange(), false);
22008
        }
22009
      }
22010
      if (nextLinePositions.length === 0) {
22011
        return getLineEndPoint(editor, forwards).filter(forwards ? isAfter : isBefore).map(pos => renderRangeCaret(editor, pos.toRange(), false));
22012
      }
22013
      return Optional.none();
22014
    };
22015
    const getLineEndPoint = (editor, forward) => {
22016
      const rng = editor.selection.getRng();
22017
      const from = forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng);
22018
      const host = getEditingHost(from.container(), editor.getBody());
22019
      if (forward) {
22020
        const lineInfo = getPositionsUntilNextLine(host, from);
22021
        return last$3(lineInfo.positions);
22022
      } else {
22023
        const lineInfo = getPositionsUntilPreviousLine(host, from);
22024
        return head(lineInfo.positions);
22025
      }
22026
    };
22027
    const moveToLineEndPoint$3 = (editor, forward, isElementPosition) => getLineEndPoint(editor, forward).filter(isElementPosition).exists(pos => {
22028
      editor.selection.setRng(pos.toRange());
22029
      return true;
22030
    });
22031
 
22032
    const setCaretPosition = (editor, pos) => {
22033
      const rng = editor.dom.createRng();
22034
      rng.setStart(pos.container(), pos.offset());
22035
      rng.setEnd(pos.container(), pos.offset());
22036
      editor.selection.setRng(rng);
22037
    };
22038
    const setSelected = (state, elm) => {
22039
      if (state) {
22040
        elm.setAttribute('data-mce-selected', 'inline-boundary');
22041
      } else {
22042
        elm.removeAttribute('data-mce-selected');
22043
      }
22044
    };
22045
    const renderCaretLocation = (editor, caret, location) => renderCaret(caret, location).map(pos => {
22046
      setCaretPosition(editor, pos);
22047
      return location;
22048
    });
22049
    const getPositionFromRange = (range, root, forward) => {
22050
      const start = CaretPosition.fromRangeStart(range);
22051
      if (range.collapsed) {
22052
        return start;
22053
      } else {
22054
        const end = CaretPosition.fromRangeEnd(range);
22055
        return forward ? prevPosition(root, end).getOr(end) : nextPosition(root, start).getOr(start);
22056
      }
22057
    };
22058
    const findLocation = (editor, caret, forward) => {
22059
      const rootNode = editor.getBody();
22060
      const from = getPositionFromRange(editor.selection.getRng(), rootNode, forward);
22061
      const isInlineTarget$1 = curry(isInlineTarget, editor);
22062
      const location = findLocation$1(forward, isInlineTarget$1, rootNode, from);
22063
      return location.bind(location => renderCaretLocation(editor, caret, location));
22064
    };
22065
    const toggleInlines = (isInlineTarget, dom, elms) => {
22066
      const inlineBoundaries = map$3(descendants(SugarElement.fromDom(dom.getRoot()), '*[data-mce-selected="inline-boundary"]'), e => e.dom);
22067
      const selectedInlines = filter$5(inlineBoundaries, isInlineTarget);
22068
      const targetInlines = filter$5(elms, isInlineTarget);
22069
      each$e(difference(selectedInlines, targetInlines), curry(setSelected, false));
22070
      each$e(difference(targetInlines, selectedInlines), curry(setSelected, true));
22071
    };
22072
    const safeRemoveCaretContainer = (editor, caret) => {
22073
      const caretValue = caret.get();
22074
      if (editor.selection.isCollapsed() && !editor.composing && caretValue) {
22075
        const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
22076
        if (CaretPosition.isTextPosition(pos) && !isAtZwsp(pos)) {
22077
          setCaretPosition(editor, removeAndReposition(caretValue, pos));
22078
          caret.set(null);
22079
        }
22080
      }
22081
    };
22082
    const renderInsideInlineCaret = (isInlineTarget, editor, caret, elms) => {
22083
      if (editor.selection.isCollapsed()) {
22084
        const inlines = filter$5(elms, isInlineTarget);
22085
        each$e(inlines, _inline => {
22086
          const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
22087
          readLocation(isInlineTarget, editor.getBody(), pos).bind(location => renderCaretLocation(editor, caret, location));
22088
        });
22089
      }
22090
    };
22091
    const move$3 = (editor, caret, forward) => isInlineBoundariesEnabled(editor) ? findLocation(editor, caret, forward).isSome() : false;
22092
    const moveWord = (forward, editor, _caret) => isInlineBoundariesEnabled(editor) ? moveByWord(forward, editor) : false;
22093
    const setupSelectedState = editor => {
22094
      const caret = Cell(null);
22095
      const isInlineTarget$1 = curry(isInlineTarget, editor);
22096
      editor.on('NodeChange', e => {
22097
        if (isInlineBoundariesEnabled(editor)) {
22098
          toggleInlines(isInlineTarget$1, editor.dom, e.parents);
22099
          safeRemoveCaretContainer(editor, caret);
22100
          renderInsideInlineCaret(isInlineTarget$1, editor, caret, e.parents);
22101
        }
22102
      });
22103
      return caret;
22104
    };
22105
    const moveNextWord = curry(moveWord, true);
22106
    const movePrevWord = curry(moveWord, false);
22107
    const moveToLineEndPoint$2 = (editor, forward, caret) => {
22108
      if (isInlineBoundariesEnabled(editor)) {
22109
        const linePoint = getLineEndPoint(editor, forward).getOrThunk(() => {
22110
          const rng = editor.selection.getRng();
22111
          return forward ? CaretPosition.fromRangeEnd(rng) : CaretPosition.fromRangeStart(rng);
22112
        });
22113
        return readLocation(curry(isInlineTarget, editor), editor.getBody(), linePoint).exists(loc => {
22114
          const outsideLoc = outside(loc);
22115
          return renderCaret(caret, outsideLoc).exists(pos => {
22116
            setCaretPosition(editor, pos);
22117
            return true;
22118
          });
22119
        });
22120
      } else {
22121
        return false;
22122
      }
22123
    };
22124
 
22125
    const rangeFromPositions = (from, to) => {
22126
      const range = document.createRange();
22127
      range.setStart(from.container(), from.offset());
22128
      range.setEnd(to.container(), to.offset());
22129
      return range;
22130
    };
22131
    const hasOnlyTwoOrLessPositionsLeft = elm => lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => {
22132
      const normalizedFirstPos = normalizePosition(true, firstPos);
22133
      const normalizedLastPos = normalizePosition(false, lastPos);
22134
      return nextPosition(elm, normalizedFirstPos).forall(pos => pos.isEqual(normalizedLastPos));
22135
    }).getOr(true);
22136
    const setCaretLocation = (editor, caret) => location => renderCaret(caret, location).map(pos => () => setCaretPosition(editor, pos));
22137
    const deleteFromTo = (editor, caret, from, to) => {
22138
      const rootNode = editor.getBody();
22139
      const isInlineTarget$1 = curry(isInlineTarget, editor);
22140
      editor.undoManager.ignore(() => {
22141
        editor.selection.setRng(rangeFromPositions(from, to));
22142
        execNativeDeleteCommand(editor);
22143
        readLocation(isInlineTarget$1, rootNode, CaretPosition.fromRangeStart(editor.selection.getRng())).map(inside).bind(setCaretLocation(editor, caret)).each(call);
22144
      });
22145
      editor.nodeChanged();
22146
    };
22147
    const rescope = (rootNode, node) => {
22148
      const parentBlock = getParentBlock$3(node, rootNode);
22149
      return parentBlock ? parentBlock : rootNode;
22150
    };
22151
    const backspaceDeleteCollapsed = (editor, caret, forward, from) => {
22152
      const rootNode = rescope(editor.getBody(), from.container());
22153
      const isInlineTarget$1 = curry(isInlineTarget, editor);
22154
      const fromLocation = readLocation(isInlineTarget$1, rootNode, from);
22155
      const location = fromLocation.bind(location => {
22156
        if (forward) {
22157
          return location.fold(constant(Optional.some(inside(location))), Optional.none, constant(Optional.some(outside(location))), Optional.none);
22158
        } else {
22159
          return location.fold(Optional.none, constant(Optional.some(outside(location))), Optional.none, constant(Optional.some(inside(location))));
22160
        }
22161
      });
22162
      return location.map(setCaretLocation(editor, caret)).getOrThunk(() => {
22163
        const toPosition = navigate(forward, rootNode, from);
22164
        const toLocation = toPosition.bind(pos => readLocation(isInlineTarget$1, rootNode, pos));
22165
        return lift2(fromLocation, toLocation, () => findRootInline(isInlineTarget$1, rootNode, from).bind(elm => {
22166
          if (hasOnlyTwoOrLessPositionsLeft(elm)) {
22167
            return Optional.some(() => {
22168
              deleteElement$2(editor, forward, SugarElement.fromDom(elm));
22169
            });
22170
          } else {
22171
            return Optional.none();
22172
          }
22173
        })).getOrThunk(() => toLocation.bind(() => toPosition.map(to => {
22174
          return () => {
22175
            if (forward) {
22176
              deleteFromTo(editor, caret, from, to);
22177
            } else {
22178
              deleteFromTo(editor, caret, to, from);
22179
            }
22180
          };
22181
        })));
22182
      });
22183
    };
22184
    const backspaceDelete$4 = (editor, caret, forward) => {
22185
      if (editor.selection.isCollapsed() && isInlineBoundariesEnabled(editor)) {
22186
        const from = CaretPosition.fromRangeStart(editor.selection.getRng());
22187
        return backspaceDeleteCollapsed(editor, caret, forward, from);
22188
      }
22189
      return Optional.none();
22190
    };
22191
 
22192
    const hasMultipleChildren = elm => childNodesCount(elm) > 1;
22193
    const getParentsUntil = (editor, pred) => {
22194
      const rootElm = SugarElement.fromDom(editor.getBody());
22195
      const startElm = SugarElement.fromDom(editor.selection.getStart());
22196
      const parents = parentsAndSelf(startElm, rootElm);
22197
      return findIndex$2(parents, pred).fold(constant(parents), index => parents.slice(0, index));
22198
    };
22199
    const hasOnlyOneChild = elm => childNodesCount(elm) === 1;
22200
    const getParentInlinesUntilMultichildInline = editor => getParentsUntil(editor, elm => editor.schema.isBlock(name(elm)) || hasMultipleChildren(elm));
22201
    const getParentInlines = editor => getParentsUntil(editor, el => editor.schema.isBlock(name(el)));
22202
    const getFormatNodes = (editor, parentInlines) => {
22203
      const isFormatElement$1 = curry(isFormatElement, editor);
22204
      return bind$3(parentInlines, elm => isFormatElement$1(elm) ? [elm.dom] : []);
22205
    };
22206
    const getFormatNodesAtStart = editor => {
22207
      const parentInlines = getParentInlines(editor);
22208
      return getFormatNodes(editor, parentInlines);
22209
    };
22210
    const deleteLastPosition = (forward, editor, target, parentInlines) => {
22211
      const formatNodes = getFormatNodes(editor, parentInlines);
22212
      if (formatNodes.length === 0) {
22213
        deleteElement$2(editor, forward, target);
22214
      } else {
22215
        const pos = replaceWithCaretFormat(target.dom, formatNodes);
22216
        editor.selection.setRng(pos.toRange());
22217
      }
22218
    };
22219
    const deleteCaret$1 = (editor, forward) => {
22220
      const parentInlines = filter$5(getParentInlinesUntilMultichildInline(editor), hasOnlyOneChild);
22221
      return last$3(parentInlines).bind(target => {
22222
        const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
22223
        if (willDeleteLastPositionInElement(forward, fromPos, target.dom) && !isEmptyCaretFormatElement(target)) {
22224
          return Optional.some(() => deleteLastPosition(forward, editor, target, parentInlines));
22225
        } else {
22226
          return Optional.none();
22227
        }
22228
      });
22229
    };
22230
    const isBrInEmptyElement = (editor, elm) => {
22231
      const parentElm = elm.parentElement;
22232
      return isBr$6(elm) && !isNull(parentElm) && editor.dom.isEmpty(parentElm);
22233
    };
22234
    const isEmptyCaret = elm => isEmptyCaretFormatElement(SugarElement.fromDom(elm));
22235
    const createCaretFormatAtStart = (editor, formatNodes) => {
22236
      const startElm = editor.selection.getStart();
22237
      const pos = isBrInEmptyElement(editor, startElm) || isEmptyCaret(startElm) ? replaceWithCaretFormat(startElm, formatNodes) : createCaretFormatAtStart$1(editor.selection.getRng(), formatNodes);
22238
      editor.selection.setRng(pos.toRange());
22239
    };
22240
    const updateCaretFormat = (editor, updateFormats) => {
22241
      const missingFormats = difference(updateFormats, getFormatNodesAtStart(editor));
22242
      if (missingFormats.length > 0) {
22243
        createCaretFormatAtStart(editor, missingFormats);
22244
      }
22245
    };
22246
    const rangeStartsAtTextContainer = rng => isText$a(rng.startContainer);
22247
    const rangeStartsAtStartOfTextContainer = rng => rng.startOffset === 0 && rangeStartsAtTextContainer(rng);
22248
    const rangeStartParentIsFormatElement = (editor, rng) => {
22249
      const startParent = rng.startContainer.parentElement;
22250
      return !isNull(startParent) && isFormatElement(editor, SugarElement.fromDom(startParent));
22251
    };
22252
    const rangeStartAndEndHaveSameParent = rng => {
22253
      const startParent = rng.startContainer.parentNode;
22254
      const endParent = rng.endContainer.parentNode;
22255
      return !isNull(startParent) && !isNull(endParent) && startParent.isEqualNode(endParent);
22256
    };
22257
    const rangeEndsAtEndOfEndContainer = rng => {
22258
      const endContainer = rng.endContainer;
22259
      return rng.endOffset === (isText$a(endContainer) ? endContainer.length : endContainer.childNodes.length);
22260
    };
22261
    const rangeEndsAtEndOfStartContainer = rng => rangeStartAndEndHaveSameParent(rng) && rangeEndsAtEndOfEndContainer(rng);
22262
    const rangeEndsAfterEndOfStartContainer = rng => !rng.endContainer.isEqualNode(rng.commonAncestorContainer);
22263
    const rangeEndsAtOrAfterEndOfStartContainer = rng => rangeEndsAtEndOfStartContainer(rng) || rangeEndsAfterEndOfStartContainer(rng);
22264
    const requiresDeleteRangeOverride = editor => {
22265
      const rng = editor.selection.getRng();
22266
      return rangeStartsAtStartOfTextContainer(rng) && rangeStartParentIsFormatElement(editor, rng) && rangeEndsAtOrAfterEndOfStartContainer(rng);
22267
    };
22268
    const deleteRange$1 = editor => {
22269
      if (requiresDeleteRangeOverride(editor)) {
22270
        const formatNodes = getFormatNodesAtStart(editor);
22271
        return Optional.some(() => {
22272
          execNativeDeleteCommand(editor);
22273
          updateCaretFormat(editor, formatNodes);
22274
        });
22275
      } else {
22276
        return Optional.none();
22277
      }
22278
    };
22279
    const backspaceDelete$3 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret$1(editor, forward) : deleteRange$1(editor);
22280
    const hasAncestorInlineCaret = (elm, schema) => ancestor$1(elm, node => isCaretNode(node.dom), el => schema.isBlock(name(el)));
22281
    const hasAncestorInlineCaretAtStart = editor => hasAncestorInlineCaret(SugarElement.fromDom(editor.selection.getStart()), editor.schema);
22282
    const requiresRefreshCaretOverride = editor => {
22283
      const rng = editor.selection.getRng();
22284
      return rng.collapsed && (rangeStartsAtTextContainer(rng) || editor.dom.isEmpty(rng.startContainer)) && !hasAncestorInlineCaretAtStart(editor);
22285
    };
22286
    const refreshCaret = editor => {
22287
      if (requiresRefreshCaretOverride(editor)) {
22288
        createCaretFormatAtStart(editor, []);
22289
      }
22290
      return true;
22291
    };
22292
 
22293
    const deleteElement = (editor, forward, element) => {
22294
      if (isNonNullable(element)) {
22295
        return Optional.some(() => {
22296
          editor._selectionOverrides.hideFakeCaret();
22297
          deleteElement$2(editor, forward, SugarElement.fromDom(element));
22298
        });
22299
      } else {
22300
        return Optional.none();
22301
      }
22302
    };
22303
    const deleteCaret = (editor, forward) => {
22304
      const isNearMedia = forward ? isBeforeMedia : isAfterMedia;
22305
      const direction = forward ? HDirection.Forwards : HDirection.Backwards;
22306
      const fromPos = getNormalizedRangeEndPoint(direction, editor.getBody(), editor.selection.getRng());
22307
      if (isNearMedia(fromPos)) {
22308
        return deleteElement(editor, forward, fromPos.getNode(!forward));
22309
      } else {
22310
        return Optional.from(normalizePosition(forward, fromPos)).filter(pos => isNearMedia(pos) && isMoveInsideSameBlock(fromPos, pos)).bind(pos => deleteElement(editor, forward, pos.getNode(!forward)));
22311
      }
22312
    };
22313
    const deleteRange = (editor, forward) => {
22314
      const selectedNode = editor.selection.getNode();
22315
      return isMedia$2(selectedNode) ? deleteElement(editor, forward, selectedNode) : Optional.none();
22316
    };
22317
    const backspaceDelete$2 = (editor, forward) => editor.selection.isCollapsed() ? deleteCaret(editor, forward) : deleteRange(editor, forward);
22318
 
22319
    const isEditable = target => closest$4(target, elm => isContentEditableTrue$3(elm.dom) || isContentEditableFalse$b(elm.dom)).exists(elm => isContentEditableTrue$3(elm.dom));
22320
    const parseIndentValue = value => toInt(value !== null && value !== void 0 ? value : '').getOr(0);
22321
    const getIndentStyleName = (useMargin, element) => {
22322
      const indentStyleName = useMargin || isTable$1(element) ? 'margin' : 'padding';
22323
      const suffix = get$7(element, 'direction') === 'rtl' ? '-right' : '-left';
22324
      return indentStyleName + suffix;
22325
    };
22326
    const indentElement = (dom, command, useMargin, value, unit, element) => {
22327
      const indentStyleName = getIndentStyleName(useMargin, SugarElement.fromDom(element));
22328
      const parsedValue = parseIndentValue(dom.getStyle(element, indentStyleName));
22329
      if (command === 'outdent') {
22330
        const styleValue = Math.max(0, parsedValue - value);
22331
        dom.setStyle(element, indentStyleName, styleValue ? styleValue + unit : '');
22332
      } else {
22333
        const styleValue = parsedValue + value + unit;
22334
        dom.setStyle(element, indentStyleName, styleValue);
22335
      }
22336
    };
22337
    const validateBlocks = (editor, blocks) => forall(blocks, block => {
22338
      const indentStyleName = getIndentStyleName(shouldIndentUseMargin(editor), block);
22339
      const intentValue = getRaw(block, indentStyleName).map(parseIndentValue).getOr(0);
22340
      const contentEditable = editor.dom.getContentEditable(block.dom);
22341
      return contentEditable !== 'false' && intentValue > 0;
22342
    });
22343
    const canOutdent = editor => {
22344
      const blocks = getBlocksToIndent(editor);
22345
      return !editor.mode.isReadOnly() && (blocks.length > 1 || validateBlocks(editor, blocks));
22346
    };
22347
    const isListComponent = el => isList(el) || isListItem$1(el);
22348
    const parentIsListComponent = el => parent(el).exists(isListComponent);
22349
    const getBlocksToIndent = editor => filter$5(fromDom$1(editor.selection.getSelectedBlocks()), el => !isListComponent(el) && !parentIsListComponent(el) && isEditable(el));
22350
    const handle = (editor, command) => {
22351
      var _a, _b;
22352
      const {dom} = editor;
22353
      const indentation = getIndentation(editor);
22354
      const indentUnit = (_b = (_a = /[a-z%]+$/i.exec(indentation)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : 'px';
22355
      const indentValue = parseIndentValue(indentation);
22356
      const useMargin = shouldIndentUseMargin(editor);
22357
      each$e(getBlocksToIndent(editor), block => {
22358
        indentElement(dom, command, useMargin, indentValue, indentUnit, block.dom);
22359
      });
22360
    };
22361
    const indent = editor => handle(editor, 'indent');
22362
    const outdent = editor => handle(editor, 'outdent');
22363
 
22364
    const backspaceDelete$1 = editor => {
22365
      if (editor.selection.isCollapsed() && canOutdent(editor)) {
22366
        const dom = editor.dom;
22367
        const rng = editor.selection.getRng();
22368
        const pos = CaretPosition.fromRangeStart(rng);
22369
        const block = dom.getParent(rng.startContainer, dom.isBlock);
22370
        if (block !== null && isAtStartOfBlock(SugarElement.fromDom(block), pos, editor.schema)) {
22371
          return Optional.some(() => outdent(editor));
22372
        }
22373
      }
22374
      return Optional.none();
22375
    };
22376
 
22377
    const findAction = (editor, caret, forward) => findMap([
22378
      backspaceDelete$1,
22379
      backspaceDelete$6,
22380
      backspaceDelete$7,
22381
      (editor, forward) => backspaceDelete$4(editor, caret, forward),
22382
      backspaceDelete$9,
22383
      backspaceDelete$a,
22384
      backspaceDelete$5,
22385
      backspaceDelete$2,
22386
      backspaceDelete$8,
22387
      backspaceDelete$3
22388
    ], item => item(editor, forward)).filter(_ => editor.selection.isEditable());
22389
    const deleteCommand = (editor, caret) => {
22390
      const result = findAction(editor, caret, false);
22391
      result.fold(() => {
22392
        if (editor.selection.isEditable()) {
22393
          execNativeDeleteCommand(editor);
22394
          paddEmptyBody(editor);
22395
        }
22396
      }, call);
22397
    };
22398
    const forwardDeleteCommand = (editor, caret) => {
22399
      const result = findAction(editor, caret, true);
22400
      result.fold(() => {
22401
        if (editor.selection.isEditable()) {
22402
          execNativeForwardDeleteCommand(editor);
22403
        }
22404
      }, call);
22405
    };
22406
    const setup$q = (editor, caret) => {
22407
      editor.addCommand('delete', () => {
22408
        deleteCommand(editor, caret);
22409
      });
22410
      editor.addCommand('forwardDelete', () => {
22411
        forwardDeleteCommand(editor, caret);
22412
      });
22413
    };
22414
 
22415
    const SIGNIFICANT_MOVE = 5;
22416
    const LONGPRESS_DELAY = 400;
22417
    const getTouch = event => {
22418
      if (event.touches === undefined || event.touches.length !== 1) {
22419
        return Optional.none();
22420
      }
22421
      return Optional.some(event.touches[0]);
22422
    };
22423
    const isFarEnough = (touch, data) => {
22424
      const distX = Math.abs(touch.clientX - data.x);
22425
      const distY = Math.abs(touch.clientY - data.y);
22426
      return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
22427
    };
22428
    const setup$p = editor => {
22429
      const startData = value$2();
22430
      const longpressFired = Cell(false);
22431
      const debounceLongpress = last$1(e => {
22432
        editor.dispatch('longpress', {
22433
          ...e,
22434
          type: 'longpress'
22435
        });
22436
        longpressFired.set(true);
22437
      }, LONGPRESS_DELAY);
22438
      editor.on('touchstart', e => {
22439
        getTouch(e).each(touch => {
22440
          debounceLongpress.cancel();
22441
          const data = {
22442
            x: touch.clientX,
22443
            y: touch.clientY,
22444
            target: e.target
22445
          };
22446
          debounceLongpress.throttle(e);
22447
          longpressFired.set(false);
22448
          startData.set(data);
22449
        });
22450
      }, true);
22451
      editor.on('touchmove', e => {
22452
        debounceLongpress.cancel();
22453
        getTouch(e).each(touch => {
22454
          startData.on(data => {
22455
            if (isFarEnough(touch, data)) {
22456
              startData.clear();
22457
              longpressFired.set(false);
22458
              editor.dispatch('longpresscancel');
22459
            }
22460
          });
22461
        });
22462
      }, true);
22463
      editor.on('touchend touchcancel', e => {
22464
        debounceLongpress.cancel();
22465
        if (e.type === 'touchcancel') {
22466
          return;
22467
        }
22468
        startData.get().filter(data => data.target.isEqualNode(e.target)).each(() => {
22469
          if (longpressFired.get()) {
22470
            e.preventDefault();
22471
          } else {
22472
            editor.dispatch('tap', {
22473
              ...e,
22474
              type: 'tap'
22475
            });
22476
          }
22477
        });
22478
      }, true);
22479
    };
22480
 
22481
    const isBlockElement = (blockElements, node) => has$2(blockElements, node.nodeName);
22482
    const isValidTarget = (schema, node) => {
22483
      if (isText$a(node)) {
22484
        return true;
22485
      } else if (isElement$6(node)) {
22486
        return !isBlockElement(schema.getBlockElements(), node) && !isBookmarkNode$1(node) && !isTransparentBlock(schema, node) && !isNonHtmlElementRoot(node);
22487
      } else {
22488
        return false;
22489
      }
22490
    };
22491
    const hasBlockParent = (blockElements, root, node) => {
22492
      return exists(parents(SugarElement.fromDom(node), SugarElement.fromDom(root)), elm => {
22493
        return isBlockElement(blockElements, elm.dom);
22494
      });
22495
    };
22496
    const shouldRemoveTextNode = (blockElements, node) => {
22497
      if (isText$a(node)) {
22498
        if (node.data.length === 0) {
22499
          return true;
22500
        } else if (/^\s+$/.test(node.data)) {
22501
          return !node.nextSibling || isBlockElement(blockElements, node.nextSibling) || isNonHtmlElementRoot(node.nextSibling);
22502
        }
22503
      }
22504
      return false;
22505
    };
22506
    const createRootBlock = editor => editor.dom.create(getForcedRootBlock(editor), getForcedRootBlockAttrs(editor));
22507
    const addRootBlocks = editor => {
22508
      const dom = editor.dom, selection = editor.selection;
22509
      const schema = editor.schema;
22510
      const blockElements = schema.getBlockElements();
22511
      const startNode = selection.getStart();
22512
      const rootNode = editor.getBody();
22513
      let rootBlockNode;
22514
      let tempNode;
22515
      let wrapped = false;
22516
      const forcedRootBlock = getForcedRootBlock(editor);
22517
      if (!startNode || !isElement$6(startNode)) {
22518
        return;
22519
      }
22520
      const rootNodeName = rootNode.nodeName.toLowerCase();
22521
      if (!schema.isValidChild(rootNodeName, forcedRootBlock.toLowerCase()) || hasBlockParent(blockElements, rootNode, startNode)) {
22522
        return;
22523
      }
22524
      const rng = selection.getRng();
22525
      const {startContainer, startOffset, endContainer, endOffset} = rng;
22526
      const restoreSelection = hasFocus(editor);
22527
      let node = rootNode.firstChild;
22528
      while (node) {
22529
        if (isElement$6(node)) {
22530
          updateElement(schema, node);
22531
        }
22532
        if (isValidTarget(schema, node)) {
22533
          if (shouldRemoveTextNode(blockElements, node)) {
22534
            tempNode = node;
22535
            node = node.nextSibling;
22536
            dom.remove(tempNode);
22537
            continue;
22538
          }
22539
          if (!rootBlockNode) {
22540
            rootBlockNode = createRootBlock(editor);
22541
            rootNode.insertBefore(rootBlockNode, node);
22542
            wrapped = true;
22543
          }
22544
          tempNode = node;
22545
          node = node.nextSibling;
22546
          rootBlockNode.appendChild(tempNode);
22547
        } else {
22548
          rootBlockNode = null;
22549
          node = node.nextSibling;
22550
        }
22551
      }
22552
      if (wrapped && restoreSelection) {
22553
        rng.setStart(startContainer, startOffset);
22554
        rng.setEnd(endContainer, endOffset);
22555
        selection.setRng(rng);
22556
        editor.nodeChanged();
22557
      }
22558
    };
22559
    const insertEmptyLine = (editor, root, insertBlock) => {
22560
      const block = SugarElement.fromDom(createRootBlock(editor));
22561
      const br = createPaddingBr();
22562
      append$1(block, br);
22563
      insertBlock(root, block);
22564
      const rng = document.createRange();
22565
      rng.setStartBefore(br.dom);
22566
      rng.setEndBefore(br.dom);
22567
      return rng;
22568
    };
22569
    const setup$o = editor => {
22570
      editor.on('NodeChange', curry(addRootBlocks, editor));
22571
    };
22572
 
22573
    const hasClass = checkClassName => node => (' ' + node.attr('class') + ' ').indexOf(checkClassName) !== -1;
22574
    const replaceMatchWithSpan = (editor, content, cls) => {
22575
      return function (match) {
22576
        const args = arguments, index = args[args.length - 2];
22577
        const prevChar = index > 0 ? content.charAt(index - 1) : '';
22578
        if (prevChar === '"') {
22579
          return match;
22580
        }
22581
        if (prevChar === '>') {
22582
          const findStartTagIndex = content.lastIndexOf('<', index);
22583
          if (findStartTagIndex !== -1) {
22584
            const tagHtml = content.substring(findStartTagIndex, index);
22585
            if (tagHtml.indexOf('contenteditable="false"') !== -1) {
22586
              return match;
22587
            }
22588
          }
22589
        }
22590
        return '<span class="' + cls + '" data-mce-content="' + editor.dom.encode(args[0]) + '">' + editor.dom.encode(typeof args[1] === 'string' ? args[1] : args[0]) + '</span>';
22591
      };
22592
    };
22593
    const convertRegExpsToNonEditable = (editor, nonEditableRegExps, e) => {
22594
      let i = nonEditableRegExps.length, content = e.content;
22595
      if (e.format === 'raw') {
22596
        return;
22597
      }
22598
      while (i--) {
22599
        content = content.replace(nonEditableRegExps[i], replaceMatchWithSpan(editor, content, getNonEditableClass(editor)));
22600
      }
22601
      e.content = content;
22602
    };
22603
    const setup$n = editor => {
22604
      const contentEditableAttrName = 'contenteditable';
22605
      const editClass = ' ' + Tools.trim(getEditableClass(editor)) + ' ';
22606
      const nonEditClass = ' ' + Tools.trim(getNonEditableClass(editor)) + ' ';
22607
      const hasEditClass = hasClass(editClass);
22608
      const hasNonEditClass = hasClass(nonEditClass);
22609
      const nonEditableRegExps = getNonEditableRegExps(editor);
22610
      if (nonEditableRegExps.length > 0) {
22611
        editor.on('BeforeSetContent', e => {
22612
          convertRegExpsToNonEditable(editor, nonEditableRegExps, e);
22613
        });
22614
      }
22615
      editor.parser.addAttributeFilter('class', nodes => {
22616
        let i = nodes.length;
22617
        while (i--) {
22618
          const node = nodes[i];
22619
          if (hasEditClass(node)) {
22620
            node.attr(contentEditableAttrName, 'true');
22621
          } else if (hasNonEditClass(node)) {
22622
            node.attr(contentEditableAttrName, 'false');
22623
          }
22624
        }
22625
      });
22626
      editor.serializer.addAttributeFilter(contentEditableAttrName, nodes => {
22627
        let i = nodes.length;
22628
        while (i--) {
22629
          const node = nodes[i];
22630
          if (!hasEditClass(node) && !hasNonEditClass(node)) {
22631
            continue;
22632
          }
22633
          if (nonEditableRegExps.length > 0 && node.attr('data-mce-content')) {
22634
            node.name = '#text';
22635
            node.type = 3;
22636
            node.raw = true;
22637
            node.value = node.attr('data-mce-content');
22638
          } else {
22639
            node.attr(contentEditableAttrName, null);
22640
          }
22641
        }
22642
      });
22643
    };
22644
 
22645
    const findBlockCaretContainer = editor => descendant$1(SugarElement.fromDom(editor.getBody()), '*[data-mce-caret]').map(elm => elm.dom).getOrNull();
22646
    const showBlockCaretContainer = (editor, blockCaretContainer) => {
22647
      if (blockCaretContainer.hasAttribute('data-mce-caret')) {
22648
        showCaretContainerBlock(blockCaretContainer);
22649
        editor.selection.setRng(editor.selection.getRng());
22650
        editor.selection.scrollIntoView(blockCaretContainer);
22651
      }
22652
    };
22653
    const handleBlockContainer = (editor, e) => {
22654
      const blockCaretContainer = findBlockCaretContainer(editor);
22655
      if (!blockCaretContainer) {
22656
        return;
22657
      }
22658
      if (e.type === 'compositionstart') {
22659
        e.preventDefault();
22660
        e.stopPropagation();
22661
        showBlockCaretContainer(editor, blockCaretContainer);
22662
        return;
22663
      }
22664
      if (hasContent(blockCaretContainer)) {
22665
        showBlockCaretContainer(editor, blockCaretContainer);
22666
        editor.undoManager.add();
22667
      }
22668
    };
22669
    const setup$m = editor => {
22670
      editor.on('keyup compositionstart', curry(handleBlockContainer, editor));
22671
    };
22672
 
22673
    const isContentEditableFalse$3 = isContentEditableFalse$b;
22674
    const moveToCeFalseHorizontally = (direction, editor, range) => moveHorizontally(editor, direction, range, isBeforeContentEditableFalse, isAfterContentEditableFalse, isContentEditableFalse$3);
22675
    const moveToCeFalseVertically = (direction, editor, range) => {
22676
      const isBefore = caretPosition => isBeforeContentEditableFalse(caretPosition) || isBeforeTable(caretPosition);
22677
      const isAfter = caretPosition => isAfterContentEditableFalse(caretPosition) || isAfterTable(caretPosition);
22678
      return moveVertically(editor, direction, range, isBefore, isAfter, isContentEditableFalse$3);
22679
    };
22680
    const createTextBlock = editor => {
22681
      const textBlock = editor.dom.create(getForcedRootBlock(editor));
22682
      textBlock.innerHTML = '<br data-mce-bogus="1">';
22683
      return textBlock;
22684
    };
22685
    const exitPreBlock = (editor, direction, range) => {
22686
      const caretWalker = CaretWalker(editor.getBody());
22687
      const getVisualCaretPosition$1 = curry(getVisualCaretPosition, direction === 1 ? caretWalker.next : caretWalker.prev);
22688
      if (range.collapsed) {
22689
        const pre = editor.dom.getParent(range.startContainer, 'PRE');
22690
        if (!pre) {
22691
          return;
22692
        }
22693
        const caretPos = getVisualCaretPosition$1(CaretPosition.fromRangeStart(range));
22694
        if (!caretPos) {
22695
          const newBlock = SugarElement.fromDom(createTextBlock(editor));
22696
          if (direction === 1) {
22697
            after$4(SugarElement.fromDom(pre), newBlock);
22698
          } else {
22699
            before$3(SugarElement.fromDom(pre), newBlock);
22700
          }
22701
          editor.selection.select(newBlock.dom, true);
22702
          editor.selection.collapse();
22703
        }
22704
      }
22705
    };
22706
    const getHorizontalRange = (editor, forward) => {
22707
      const direction = forward ? HDirection.Forwards : HDirection.Backwards;
22708
      const range = editor.selection.getRng();
22709
      return moveToCeFalseHorizontally(direction, editor, range).orThunk(() => {
22710
        exitPreBlock(editor, direction, range);
22711
        return Optional.none();
22712
      });
22713
    };
22714
    const getVerticalRange = (editor, down) => {
22715
      const direction = down ? 1 : -1;
22716
      const range = editor.selection.getRng();
22717
      return moveToCeFalseVertically(direction, editor, range).orThunk(() => {
22718
        exitPreBlock(editor, direction, range);
22719
        return Optional.none();
22720
      });
22721
    };
22722
    const flipDirection = (selection, forward) => {
22723
      const elm = forward ? selection.getEnd(true) : selection.getStart(true);
22724
      return isRtl(elm) ? !forward : forward;
22725
    };
22726
    const moveH$2 = (editor, forward) => getHorizontalRange(editor, flipDirection(editor.selection, forward)).exists(newRange => {
22727
      moveToRange(editor, newRange);
22728
      return true;
22729
    });
22730
    const moveV$4 = (editor, down) => getVerticalRange(editor, down).exists(newRange => {
22731
      moveToRange(editor, newRange);
22732
      return true;
22733
    });
22734
    const moveToLineEndPoint$1 = (editor, forward) => {
22735
      const isCefPosition = forward ? isAfterContentEditableFalse : isBeforeContentEditableFalse;
22736
      return moveToLineEndPoint$3(editor, forward, isCefPosition);
22737
    };
22738
    const selectToEndPoint = (editor, forward) => getEdgeCefPosition(editor, !forward).map(pos => {
22739
      const rng = pos.toRange();
22740
      const curRng = editor.selection.getRng();
22741
      if (forward) {
22742
        rng.setStart(curRng.startContainer, curRng.startOffset);
22743
      } else {
22744
        rng.setEnd(curRng.endContainer, curRng.endOffset);
22745
      }
22746
      return rng;
22747
    }).exists(rng => {
22748
      moveToRange(editor, rng);
22749
      return true;
22750
    });
22751
 
22752
    const isTarget = node => contains$2(['figcaption'], name(node));
22753
    const getClosestTargetBlock = (pos, root, schema) => {
22754
      const isRoot = curry(eq, root);
22755
      return closest$4(SugarElement.fromDom(pos.container()), el => schema.isBlock(name(el)), isRoot).filter(isTarget);
22756
    };
22757
    const isAtFirstOrLastLine = (root, forward, pos) => forward ? isAtLastLine(root.dom, pos) : isAtFirstLine(root.dom, pos);
22758
    const moveCaretToNewEmptyLine = (editor, forward) => {
22759
      const root = SugarElement.fromDom(editor.getBody());
22760
      const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
22761
      return getClosestTargetBlock(pos, root, editor.schema).exists(() => {
22762
        if (isAtFirstOrLastLine(root, forward, pos)) {
22763
          const insertFn = forward ? append$1 : prepend;
22764
          const rng = insertEmptyLine(editor, root, insertFn);
22765
          editor.selection.setRng(rng);
22766
          return true;
22767
        } else {
22768
          return false;
22769
        }
22770
      });
22771
    };
22772
    const moveV$3 = (editor, forward) => {
22773
      if (editor.selection.isCollapsed()) {
22774
        return moveCaretToNewEmptyLine(editor, forward);
22775
      } else {
22776
        return false;
22777
      }
22778
    };
22779
 
22780
    const moveUp = (editor, details, summary) => {
22781
      const rng = editor.selection.getRng();
22782
      const pos = CaretPosition.fromRangeStart(rng);
22783
      const root = editor.getBody();
22784
      if (root.firstChild === details && isAtFirstLine(summary, pos)) {
22785
        editor.execCommand('InsertNewBlockBefore');
22786
        return true;
22787
      } else {
22788
        return false;
22789
      }
22790
    };
22791
    const moveDown = (editor, details) => {
22792
      const rng = editor.selection.getRng();
22793
      const pos = CaretPosition.fromRangeStart(rng);
22794
      const root = editor.getBody();
22795
      if (root.lastChild === details && isAtLastLine(details, pos)) {
22796
        editor.execCommand('InsertNewBlockAfter');
22797
        return true;
22798
      } else {
22799
        return false;
22800
      }
22801
    };
22802
    const move$2 = (editor, forward) => {
22803
      if (forward) {
22804
        return Optional.from(editor.dom.getParent(editor.selection.getNode(), 'details')).map(details => moveDown(editor, details)).getOr(false);
22805
      } else {
22806
        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);
22807
      }
22808
    };
22809
    const moveV$2 = (editor, forward) => move$2(editor, forward);
22810
 
22811
    const baseKeyPattern = {
22812
      shiftKey: false,
22813
      altKey: false,
22814
      ctrlKey: false,
22815
      metaKey: false,
22816
      keyCode: 0
22817
    };
22818
    const defaultPatterns = patterns => map$3(patterns, pattern => ({
22819
      ...baseKeyPattern,
22820
      ...pattern
22821
    }));
22822
    const defaultDelayedPatterns = patterns => map$3(patterns, pattern => ({
22823
      ...baseKeyPattern,
22824
      ...pattern
22825
    }));
22826
    const matchesEvent = (pattern, evt) => evt.keyCode === pattern.keyCode && evt.shiftKey === pattern.shiftKey && evt.altKey === pattern.altKey && evt.ctrlKey === pattern.ctrlKey && evt.metaKey === pattern.metaKey;
22827
    const match$1 = (patterns, evt) => bind$3(defaultPatterns(patterns), pattern => matchesEvent(pattern, evt) ? [pattern] : []);
22828
    const matchDelayed = (patterns, evt) => bind$3(defaultDelayedPatterns(patterns), pattern => matchesEvent(pattern, evt) ? [pattern] : []);
22829
    const action = (f, ...x) => () => f.apply(null, x);
22830
    const execute = (patterns, evt) => find$2(match$1(patterns, evt), pattern => pattern.action());
22831
    const executeWithDelayedAction = (patterns, evt) => findMap(matchDelayed(patterns, evt), pattern => pattern.action());
22832
 
22833
    const moveH$1 = (editor, forward) => {
22834
      const direction = forward ? HDirection.Forwards : HDirection.Backwards;
22835
      const range = editor.selection.getRng();
22836
      return moveHorizontally(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists(newRange => {
22837
        moveToRange(editor, newRange);
22838
        return true;
22839
      });
22840
    };
22841
    const moveV$1 = (editor, down) => {
22842
      const direction = down ? 1 : -1;
22843
      const range = editor.selection.getRng();
22844
      return moveVertically(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists(newRange => {
22845
        moveToRange(editor, newRange);
22846
        return true;
22847
      });
22848
    };
22849
    const moveToLineEndPoint = (editor, forward) => {
22850
      const isNearMedia = forward ? isAfterMedia : isBeforeMedia;
22851
      return moveToLineEndPoint$3(editor, forward, isNearMedia);
22852
    };
22853
 
22854
    const adt = Adt.generate([
22855
      { none: ['current'] },
22856
      { first: ['current'] },
22857
      {
22858
        middle: [
22859
          'current',
22860
          'target'
22861
        ]
22862
      },
22863
      { last: ['current'] }
22864
    ]);
22865
    const none = current => adt.none(current);
22866
    const CellLocation = {
22867
      ...adt,
22868
      none
22869
    };
22870
 
22871
    const firstLayer = (scope, selector) => {
22872
      return filterFirstLayer(scope, selector, always);
22873
    };
22874
    const filterFirstLayer = (scope, selector, predicate) => {
22875
      return bind$3(children$1(scope), x => {
22876
        if (is$1(x, selector)) {
22877
          return predicate(x) ? [x] : [];
22878
        } else {
22879
          return filterFirstLayer(x, selector, predicate);
22880
        }
22881
      });
22882
    };
22883
 
22884
    const lookup$1 = (tags, element, isRoot = never) => {
22885
      if (isRoot(element)) {
22886
        return Optional.none();
22887
      }
22888
      if (contains$2(tags, name(element))) {
22889
        return Optional.some(element);
22890
      }
22891
      const isRootOrUpperTable = elm => is$1(elm, 'table') || isRoot(elm);
22892
      return ancestor$3(element, tags.join(','), isRootOrUpperTable);
22893
    };
22894
    const cell = (element, isRoot) => lookup$1([
22895
      'td',
22896
      'th'
22897
    ], element, isRoot);
22898
    const cells = ancestor => firstLayer(ancestor, 'th,td');
22899
    const table = (element, isRoot) => closest$3(element, 'table', isRoot);
22900
 
22901
    const walk = (all, current, index, direction, isEligible = always) => {
22902
      const forwards = direction === 1;
22903
      if (!forwards && index <= 0) {
22904
        return CellLocation.first(all[0]);
22905
      } else if (forwards && index >= all.length - 1) {
22906
        return CellLocation.last(all[all.length - 1]);
22907
      } else {
22908
        const newIndex = index + direction;
22909
        const elem = all[newIndex];
22910
        return isEligible(elem) ? CellLocation.middle(current, elem) : walk(all, current, newIndex, direction, isEligible);
22911
      }
22912
    };
22913
    const detect = (current, isRoot) => {
22914
      return table(current, isRoot).bind(table => {
22915
        const all = cells(table);
22916
        const index = findIndex$2(all, x => eq(current, x));
22917
        return index.map(index => ({
22918
          index,
22919
          all
22920
        }));
22921
      });
22922
    };
22923
    const next = (current, isEligible, isRoot) => {
22924
      const detection = detect(current, isRoot);
22925
      return detection.fold(() => {
22926
        return CellLocation.none(current);
22927
      }, info => {
22928
        return walk(info.all, current, info.index, 1, isEligible);
22929
      });
22930
    };
22931
    const prev = (current, isEligible, isRoot) => {
22932
      const detection = detect(current, isRoot);
22933
      return detection.fold(() => {
22934
        return CellLocation.none();
22935
      }, info => {
22936
        return walk(info.all, current, info.index, -1, isEligible);
22937
      });
22938
    };
22939
 
22940
    const deflate = (rect, delta) => ({
22941
      left: rect.left - delta,
22942
      top: rect.top - delta,
22943
      right: rect.right + delta * 2,
22944
      bottom: rect.bottom + delta * 2,
22945
      width: rect.width + delta,
22946
      height: rect.height + delta
22947
    });
22948
    const getCorners = (getYAxisValue, tds) => bind$3(tds, td => {
22949
      const rect = deflate(clone$1(td.getBoundingClientRect()), -1);
22950
      return [
22951
        {
22952
          x: rect.left,
22953
          y: getYAxisValue(rect),
22954
          cell: td
22955
        },
22956
        {
22957
          x: rect.right,
22958
          y: getYAxisValue(rect),
22959
          cell: td
22960
        }
22961
      ];
22962
    });
22963
    const findClosestCorner = (corners, x, y) => foldl(corners, (acc, newCorner) => acc.fold(() => Optional.some(newCorner), oldCorner => {
22964
      const oldDist = Math.sqrt(Math.abs(oldCorner.x - x) + Math.abs(oldCorner.y - y));
22965
      const newDist = Math.sqrt(Math.abs(newCorner.x - x) + Math.abs(newCorner.y - y));
22966
      return Optional.some(newDist < oldDist ? newCorner : oldCorner);
22967
    }), Optional.none());
22968
    const getClosestCell = (getYAxisValue, isTargetCorner, table, x, y) => {
22969
      const cells = descendants(SugarElement.fromDom(table), 'td,th,caption').map(e => e.dom);
22970
      const corners = filter$5(getCorners(getYAxisValue, cells), corner => isTargetCorner(corner, y));
22971
      return findClosestCorner(corners, x, y).map(corner => corner.cell);
22972
    };
22973
    const getBottomValue = rect => rect.bottom;
22974
    const getTopValue = rect => rect.top;
22975
    const isAbove = (corner, y) => corner.y < y;
22976
    const isBelow = (corner, y) => corner.y > y;
22977
    const getClosestCellAbove = curry(getClosestCell, getBottomValue, isAbove);
22978
    const getClosestCellBelow = curry(getClosestCell, getTopValue, isBelow);
22979
    const findClosestPositionInAboveCell = (table, pos) => head(pos.getClientRects()).bind(rect => getClosestCellAbove(table, rect.left, rect.top)).bind(cell => findClosestHorizontalPosition(getLastLinePositions(cell), pos));
22980
    const findClosestPositionInBelowCell = (table, pos) => last$3(pos.getClientRects()).bind(rect => getClosestCellBelow(table, rect.left, rect.top)).bind(cell => findClosestHorizontalPosition(getFirstLinePositions(cell), pos));
22981
 
22982
    const hasNextBreak = (getPositionsUntil, scope, lineInfo) => lineInfo.breakAt.exists(breakPos => getPositionsUntil(scope, breakPos).breakAt.isSome());
22983
    const startsWithWrapBreak = lineInfo => lineInfo.breakType === BreakType.Wrap && lineInfo.positions.length === 0;
22984
    const startsWithBrBreak = lineInfo => lineInfo.breakType === BreakType.Br && lineInfo.positions.length === 1;
22985
    const isAtTableCellLine = (getPositionsUntil, scope, pos) => {
22986
      const lineInfo = getPositionsUntil(scope, pos);
22987
      if (startsWithWrapBreak(lineInfo) || !isBr$6(pos.getNode()) && startsWithBrBreak(lineInfo)) {
22988
        return !hasNextBreak(getPositionsUntil, scope, lineInfo);
22989
      } else {
22990
        return lineInfo.breakAt.isNone();
22991
      }
22992
    };
22993
    const isAtFirstTableCellLine = curry(isAtTableCellLine, getPositionsUntilPreviousLine);
22994
    const isAtLastTableCellLine = curry(isAtTableCellLine, getPositionsUntilNextLine);
22995
    const isCaretAtStartOrEndOfTable = (forward, rng, table) => {
22996
      const caretPos = CaretPosition.fromRangeStart(rng);
22997
      return positionIn(!forward, table).exists(pos => pos.isEqual(caretPos));
22998
    };
22999
    const navigateHorizontally = (editor, forward, table, _td) => {
23000
      const rng = editor.selection.getRng();
23001
      const direction = forward ? 1 : -1;
23002
      if (isFakeCaretTableBrowser() && isCaretAtStartOrEndOfTable(forward, rng, table)) {
23003
        showCaret(direction, editor, table, !forward, false).each(newRng => {
23004
          moveToRange(editor, newRng);
23005
        });
23006
        return true;
23007
      }
23008
      return false;
23009
    };
23010
    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));
23011
    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));
23012
    const getTable = (previous, pos) => {
23013
      const node = pos.getNode(previous);
23014
      return isTable$2(node) ? Optional.some(node) : Optional.none();
23015
    };
23016
    const renderBlock = (down, editor, table) => {
23017
      editor.undoManager.transact(() => {
23018
        const insertFn = down ? after$4 : before$3;
23019
        const rng = insertEmptyLine(editor, SugarElement.fromDom(table), insertFn);
23020
        moveToRange(editor, rng);
23021
      });
23022
    };
23023
    const moveCaret = (editor, down, pos) => {
23024
      const table = down ? getTable(true, pos) : getTable(false, pos);
23025
      const last = down === false;
23026
      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)));
23027
    };
23028
    const navigateVertically = (editor, down, table, td) => {
23029
      const rng = editor.selection.getRng();
23030
      const pos = CaretPosition.fromRangeStart(rng);
23031
      const root = editor.getBody();
23032
      if (!down && isAtFirstTableCellLine(td, pos)) {
23033
        const newPos = getClosestAbovePosition(root, table, pos);
23034
        moveCaret(editor, down, newPos);
23035
        return true;
23036
      } else if (down && isAtLastTableCellLine(td, pos)) {
23037
        const newPos = getClosestBelowPosition(root, table, pos);
23038
        moveCaret(editor, down, newPos);
23039
        return true;
23040
      } else {
23041
        return false;
23042
      }
23043
    };
23044
    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);
23045
    const moveH = (editor, forward) => move$1(editor, forward, navigateHorizontally);
23046
    const moveV = (editor, forward) => move$1(editor, forward, navigateVertically);
23047
    const getCellFirstCursorPosition = cell => {
23048
      const selection = SimSelection.exact(cell, 0, cell, 0);
23049
      return toNative(selection);
23050
    };
23051
    const tabGo = (editor, isRoot, cell) => {
23052
      return cell.fold(Optional.none, Optional.none, (_current, next) => {
23053
        return first(next).map(cell => {
23054
          return getCellFirstCursorPosition(cell);
23055
        });
23056
      }, current => {
23057
        editor.execCommand('mceTableInsertRowAfter');
23058
        return tabForward(editor, isRoot, current);
23059
      });
23060
    };
23061
    const tabForward = (editor, isRoot, cell) => tabGo(editor, isRoot, next(cell, isEditable$2));
23062
    const tabBackward = (editor, isRoot, cell) => tabGo(editor, isRoot, prev(cell, isEditable$2));
23063
    const handleTab = (editor, forward) => {
23064
      const rootElements = [
23065
        'table',
23066
        'li',
23067
        'dl'
23068
      ];
23069
      const body = SugarElement.fromDom(editor.getBody());
23070
      const isRoot = element => {
23071
        const name$1 = name(element);
23072
        return eq(element, body) || contains$2(rootElements, name$1);
23073
      };
23074
      const rng = editor.selection.getRng();
23075
      const container = SugarElement.fromDom(!forward ? rng.startContainer : rng.endContainer);
23076
      return cell(container, isRoot).map(cell => {
23077
        table(cell, isRoot).each(table => {
23078
          editor.model.table.clearSelectedCells(table.dom);
23079
        });
23080
        editor.selection.collapse(!forward);
23081
        const navigation = !forward ? tabBackward : tabForward;
23082
        const rng = navigation(editor, isRoot, cell);
23083
        rng.each(range => {
23084
          editor.selection.setRng(range);
23085
        });
23086
        return true;
23087
      }).getOr(false);
23088
    };
23089
 
23090
    const executeKeydownOverride$4 = (editor, caret, evt) => {
23091
      const isMac = Env.os.isMacOS() || Env.os.isiOS();
23092
      execute([
23093
        {
23094
          keyCode: VK.RIGHT,
23095
          action: action(moveH$2, editor, true)
23096
        },
23097
        {
23098
          keyCode: VK.LEFT,
23099
          action: action(moveH$2, editor, false)
23100
        },
23101
        {
23102
          keyCode: VK.UP,
23103
          action: action(moveV$4, editor, false)
23104
        },
23105
        {
23106
          keyCode: VK.DOWN,
23107
          action: action(moveV$4, editor, true)
23108
        },
23109
        ...isMac ? [
23110
          {
23111
            keyCode: VK.UP,
23112
            action: action(selectToEndPoint, editor, false),
23113
            metaKey: true,
23114
            shiftKey: true
23115
          },
23116
          {
23117
            keyCode: VK.DOWN,
23118
            action: action(selectToEndPoint, editor, true),
23119
            metaKey: true,
23120
            shiftKey: true
23121
          }
23122
        ] : [],
23123
        {
23124
          keyCode: VK.RIGHT,
23125
          action: action(moveH, editor, true)
23126
        },
23127
        {
23128
          keyCode: VK.LEFT,
23129
          action: action(moveH, editor, false)
23130
        },
23131
        {
23132
          keyCode: VK.UP,
23133
          action: action(moveV, editor, false)
23134
        },
23135
        {
23136
          keyCode: VK.DOWN,
23137
          action: action(moveV, editor, true)
23138
        },
23139
        {
23140
          keyCode: VK.UP,
23141
          action: action(moveV, editor, false)
23142
        },
23143
        {
23144
          keyCode: VK.UP,
23145
          action: action(moveV$2, editor, false)
23146
        },
23147
        {
23148
          keyCode: VK.DOWN,
23149
          action: action(moveV$2, editor, true)
23150
        },
23151
        {
23152
          keyCode: VK.RIGHT,
23153
          action: action(moveH$1, editor, true)
23154
        },
23155
        {
23156
          keyCode: VK.LEFT,
23157
          action: action(moveH$1, editor, false)
23158
        },
23159
        {
23160
          keyCode: VK.UP,
23161
          action: action(moveV$1, editor, false)
23162
        },
23163
        {
23164
          keyCode: VK.DOWN,
23165
          action: action(moveV$1, editor, true)
23166
        },
23167
        {
23168
          keyCode: VK.RIGHT,
23169
          action: action(move$3, editor, caret, true)
23170
        },
23171
        {
23172
          keyCode: VK.LEFT,
23173
          action: action(move$3, editor, caret, false)
23174
        },
23175
        {
23176
          keyCode: VK.RIGHT,
23177
          ctrlKey: !isMac,
23178
          altKey: isMac,
23179
          action: action(moveNextWord, editor, caret)
23180
        },
23181
        {
23182
          keyCode: VK.LEFT,
23183
          ctrlKey: !isMac,
23184
          altKey: isMac,
23185
          action: action(movePrevWord, editor, caret)
23186
        },
23187
        {
23188
          keyCode: VK.UP,
23189
          action: action(moveV$3, editor, false)
23190
        },
23191
        {
23192
          keyCode: VK.DOWN,
23193
          action: action(moveV$3, editor, true)
23194
        }
23195
      ], evt).each(_ => {
23196
        evt.preventDefault();
23197
      });
23198
    };
23199
    const setup$l = (editor, caret) => {
23200
      editor.on('keydown', evt => {
23201
        if (!evt.isDefaultPrevented()) {
23202
          executeKeydownOverride$4(editor, caret, evt);
23203
        }
23204
      });
23205
    };
23206
 
23207
    const point = (container, offset) => ({
23208
      container,
23209
      offset
23210
    });
23211
 
23212
    const DOM$7 = DOMUtils.DOM;
23213
    const alwaysNext = startNode => node => startNode === node ? -1 : 0;
23214
    const isBoundary = dom => node => dom.isBlock(node) || contains$2([
23215
      'BR',
23216
      'IMG',
23217
      'HR',
23218
      'INPUT'
23219
    ], node.nodeName) || dom.getContentEditable(node) === 'false';
23220
    const textBefore = (node, offset, rootNode) => {
23221
      if (isText$a(node) && offset >= 0) {
23222
        return Optional.some(point(node, offset));
23223
      } else {
23224
        const textSeeker = TextSeeker(DOM$7);
23225
        return Optional.from(textSeeker.backwards(node, offset, alwaysNext(node), rootNode)).map(prev => point(prev.container, prev.container.data.length));
23226
      }
23227
    };
23228
    const textAfter = (node, offset, rootNode) => {
23229
      if (isText$a(node) && offset >= node.length) {
23230
        return Optional.some(point(node, offset));
23231
      } else {
23232
        const textSeeker = TextSeeker(DOM$7);
23233
        return Optional.from(textSeeker.forwards(node, offset, alwaysNext(node), rootNode)).map(prev => point(prev.container, 0));
23234
      }
23235
    };
23236
    const scanLeft = (node, offset, rootNode) => {
23237
      if (!isText$a(node)) {
23238
        return Optional.none();
23239
      }
23240
      const text = node.data;
23241
      if (offset >= 0 && offset <= text.length) {
23242
        return Optional.some(point(node, offset));
23243
      } else {
23244
        const textSeeker = TextSeeker(DOM$7);
23245
        return Optional.from(textSeeker.backwards(node, offset, alwaysNext(node), rootNode)).bind(prev => {
23246
          const prevText = prev.container.data;
23247
          return scanLeft(prev.container, offset + prevText.length, rootNode);
23248
        });
23249
      }
23250
    };
23251
    const scanRight = (node, offset, rootNode) => {
23252
      if (!isText$a(node)) {
23253
        return Optional.none();
23254
      }
23255
      const text = node.data;
23256
      if (offset <= text.length) {
23257
        return Optional.some(point(node, offset));
23258
      } else {
23259
        const textSeeker = TextSeeker(DOM$7);
23260
        return Optional.from(textSeeker.forwards(node, offset, alwaysNext(node), rootNode)).bind(next => scanRight(next.container, offset - text.length, rootNode));
23261
      }
23262
    };
23263
    const repeatLeft = (dom, node, offset, process, rootNode) => {
23264
      const search = TextSeeker(dom, isBoundary(dom));
23265
      return Optional.from(search.backwards(node, offset, process, rootNode));
23266
    };
23267
 
23268
    const isValidTextRange = rng => rng.collapsed && isText$a(rng.startContainer);
23269
    const getText = rng => trim$2(rng.toString().replace(/\u00A0/g, ' '));
23270
    const isWhitespace = chr => chr !== '' && ' \xA0\f\n\r\t\x0B'.indexOf(chr) !== -1;
23271
 
23272
    const stripTrigger = (text, trigger) => text.substring(trigger.length);
23273
    const findTrigger = (text, index, trigger) => {
23274
      let i;
23275
      const firstChar = trigger.charAt(0);
23276
      for (i = index - 1; i >= 0; i--) {
23277
        const char = text.charAt(i);
23278
        if (isWhitespace(char)) {
23279
          return Optional.none();
23280
        }
23281
        if (firstChar === char && contains$1(text, trigger, i, index)) {
23282
          break;
23283
        }
23284
      }
23285
      return Optional.some(i);
23286
    };
23287
    const findStart = (dom, initRange, trigger, minChars = 0) => {
23288
      if (!isValidTextRange(initRange)) {
23289
        return Optional.none();
23290
      }
23291
      const buffer = {
23292
        text: '',
23293
        offset: 0
23294
      };
23295
      const findTriggerIndex = (element, offset, text) => {
23296
        buffer.text = text + buffer.text;
23297
        buffer.offset += offset;
23298
        return findTrigger(buffer.text, buffer.offset, trigger).getOr(offset);
23299
      };
23300
      const root = dom.getParent(initRange.startContainer, dom.isBlock) || dom.getRoot();
23301
      return repeatLeft(dom, initRange.startContainer, initRange.startOffset, findTriggerIndex, root).bind(spot => {
23302
        const range = initRange.cloneRange();
23303
        range.setStart(spot.container, spot.offset);
23304
        range.setEnd(initRange.endContainer, initRange.endOffset);
23305
        if (range.collapsed) {
23306
          return Optional.none();
23307
        }
23308
        const text = getText(range);
23309
        const triggerIndex = text.lastIndexOf(trigger);
23310
        if (triggerIndex !== 0 || stripTrigger(text, trigger).length < minChars) {
23311
          return Optional.none();
23312
        } else {
23313
          return Optional.some({
23314
            text: stripTrigger(text, trigger),
23315
            range,
23316
            trigger
23317
          });
23318
        }
23319
      });
23320
    };
23321
    const getContext = (dom, initRange, trigger, minChars = 0) => detect$1(SugarElement.fromDom(initRange.startContainer)).fold(() => findStart(dom, initRange, trigger, minChars), elm => {
23322
      const range = dom.createRng();
23323
      range.selectNode(elm.dom);
23324
      const text = getText(range);
23325
      return Optional.some({
23326
        range,
23327
        text: stripTrigger(text, trigger),
23328
        trigger
23329
      });
23330
    });
23331
 
23332
    const isText$1 = node => node.nodeType === TEXT;
23333
    const isElement = node => node.nodeType === ELEMENT;
23334
    const toLast = node => {
23335
      if (isText$1(node)) {
23336
        return point(node, node.data.length);
23337
      } else {
23338
        const children = node.childNodes;
23339
        return children.length > 0 ? toLast(children[children.length - 1]) : point(node, children.length);
23340
      }
23341
    };
23342
    const toLeaf = (node, offset) => {
23343
      const children = node.childNodes;
23344
      if (children.length > 0 && offset < children.length) {
23345
        return toLeaf(children[offset], 0);
23346
      } else if (children.length > 0 && isElement(node) && children.length === offset) {
23347
        return toLast(children[children.length - 1]);
23348
      } else {
23349
        return point(node, offset);
23350
      }
23351
    };
23352
 
23353
    const isPreviousCharContent = (dom, leaf) => {
23354
      var _a;
23355
      const root = (_a = dom.getParent(leaf.container, dom.isBlock)) !== null && _a !== void 0 ? _a : dom.getRoot();
23356
      return repeatLeft(dom, leaf.container, leaf.offset, (_element, offset) => offset === 0 ? -1 : offset, root).filter(spot => {
23357
        const char = spot.container.data.charAt(spot.offset - 1);
23358
        return !isWhitespace(char);
23359
      }).isSome();
23360
    };
23361
    const isStartOfWord = dom => rng => {
23362
      const leaf = toLeaf(rng.startContainer, rng.startOffset);
23363
      return !isPreviousCharContent(dom, leaf);
23364
    };
23365
    const getTriggerContext = (dom, initRange, database) => findMap(database.triggers, trigger => getContext(dom, initRange, trigger));
23366
    const lookup = (editor, getDatabase) => {
23367
      const database = getDatabase();
23368
      const rng = editor.selection.getRng();
23369
      return getTriggerContext(editor.dom, rng, database).bind(context => lookupWithContext(editor, getDatabase, context));
23370
    };
23371
    const lookupWithContext = (editor, getDatabase, context, fetchOptions = {}) => {
23372
      var _a;
23373
      const database = getDatabase();
23374
      const rng = editor.selection.getRng();
23375
      const startText = (_a = rng.startContainer.nodeValue) !== null && _a !== void 0 ? _a : '';
23376
      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));
23377
      if (autocompleters.length === 0) {
23378
        return Optional.none();
23379
      }
23380
      const lookupData = Promise.all(map$3(autocompleters, ac => {
23381
        const fetchResult = ac.fetch(context.text, ac.maxResults, fetchOptions);
23382
        return fetchResult.then(results => ({
23383
          matchText: context.text,
23384
          items: results,
23385
          columns: ac.columns,
23386
          onAction: ac.onAction,
23387
          highlightOn: ac.highlightOn
23388
        }));
23389
      }));
23390
      return Optional.some({
23391
        lookupData,
23392
        context
23393
      });
23394
    };
23395
 
23396
    var SimpleResultType;
23397
    (function (SimpleResultType) {
23398
      SimpleResultType[SimpleResultType['Error'] = 0] = 'Error';
23399
      SimpleResultType[SimpleResultType['Value'] = 1] = 'Value';
23400
    }(SimpleResultType || (SimpleResultType = {})));
23401
    const fold$1 = (res, onError, onValue) => res.stype === SimpleResultType.Error ? onError(res.serror) : onValue(res.svalue);
23402
    const partition = results => {
23403
      const values = [];
23404
      const errors = [];
23405
      each$e(results, obj => {
23406
        fold$1(obj, err => errors.push(err), val => values.push(val));
23407
      });
23408
      return {
23409
        values,
23410
        errors
23411
      };
23412
    };
23413
    const mapError = (res, f) => {
23414
      if (res.stype === SimpleResultType.Error) {
23415
        return {
23416
          stype: SimpleResultType.Error,
23417
          serror: f(res.serror)
23418
        };
23419
      } else {
23420
        return res;
23421
      }
23422
    };
23423
    const map = (res, f) => {
23424
      if (res.stype === SimpleResultType.Value) {
23425
        return {
23426
          stype: SimpleResultType.Value,
23427
          svalue: f(res.svalue)
23428
        };
23429
      } else {
23430
        return res;
23431
      }
23432
    };
23433
    const bind$1 = (res, f) => {
23434
      if (res.stype === SimpleResultType.Value) {
23435
        return f(res.svalue);
23436
      } else {
23437
        return res;
23438
      }
23439
    };
23440
    const bindError = (res, f) => {
23441
      if (res.stype === SimpleResultType.Error) {
23442
        return f(res.serror);
23443
      } else {
23444
        return res;
23445
      }
23446
    };
23447
    const svalue = v => ({
23448
      stype: SimpleResultType.Value,
23449
      svalue: v
23450
    });
23451
    const serror = e => ({
23452
      stype: SimpleResultType.Error,
23453
      serror: e
23454
    });
23455
    const toResult = res => fold$1(res, Result.error, Result.value);
23456
    const fromResult = res => res.fold(serror, svalue);
23457
    const SimpleResult = {
23458
      fromResult,
23459
      toResult,
23460
      svalue,
23461
      partition,
23462
      serror,
23463
      bind: bind$1,
23464
      bindError,
23465
      map,
23466
      mapError,
23467
      fold: fold$1
23468
    };
23469
 
23470
    const formatObj = input => {
23471
      return isObject(input) && keys(input).length > 100 ? ' removed due to size' : JSON.stringify(input, null, 2);
23472
    };
23473
    const formatErrors = errors => {
23474
      const es = errors.length > 10 ? errors.slice(0, 10).concat([{
23475
          path: [],
23476
          getErrorInfo: constant('... (only showing first ten failures)')
23477
        }]) : errors;
23478
      return map$3(es, e => {
23479
        return 'Failed path: (' + e.path.join(' > ') + ')\n' + e.getErrorInfo();
23480
      });
23481
    };
23482
 
23483
    const nu = (path, getErrorInfo) => {
23484
      return SimpleResult.serror([{
23485
          path,
23486
          getErrorInfo
23487
        }]);
23488
    };
23489
    const missingRequired = (path, key, obj) => nu(path, () => 'Could not find valid *required* value for "' + key + '" in ' + formatObj(obj));
23490
    const missingKey = (path, key) => nu(path, () => 'Choice schema did not contain choice key: "' + key + '"');
23491
    const missingBranch = (path, branches, branch) => nu(path, () => 'The chosen schema: "' + branch + '" did not exist in branches: ' + formatObj(branches));
23492
    const custom = (path, err) => nu(path, constant(err));
23493
 
23494
    const chooseFrom = (path, input, branches, ch) => {
23495
      const fields = get$a(branches, ch);
23496
      return fields.fold(() => missingBranch(path, branches, ch), vp => vp.extract(path.concat(['branch: ' + ch]), input));
23497
    };
23498
    const choose$1 = (key, branches) => {
23499
      const extract = (path, input) => {
23500
        const choice = get$a(input, key);
23501
        return choice.fold(() => missingKey(path, key), chosen => chooseFrom(path, input, branches, chosen));
23502
      };
23503
      const toString = () => 'chooseOn(' + key + '). Possible values: ' + keys(branches);
23504
      return {
23505
        extract,
23506
        toString
23507
      };
23508
    };
23509
 
23510
    const shallow = (old, nu) => {
23511
      return nu;
23512
    };
23513
    const deep = (old, nu) => {
23514
      const bothObjects = isPlainObject(old) && isPlainObject(nu);
23515
      return bothObjects ? deepMerge(old, nu) : nu;
23516
    };
23517
    const baseMerge = merger => {
23518
      return (...objects) => {
23519
        if (objects.length === 0) {
23520
          throw new Error(`Can't merge zero objects`);
23521
        }
23522
        const ret = {};
23523
        for (let j = 0; j < objects.length; j++) {
23524
          const curObject = objects[j];
23525
          for (const key in curObject) {
23526
            if (has$2(curObject, key)) {
23527
              ret[key] = merger(ret[key], curObject[key]);
23528
            }
23529
          }
23530
        }
23531
        return ret;
23532
      };
23533
    };
23534
    const deepMerge = baseMerge(deep);
23535
    const merge = baseMerge(shallow);
23536
 
23537
    const required = () => ({
23538
      tag: 'required',
23539
      process: {}
23540
    });
23541
    const defaultedThunk = fallbackThunk => ({
23542
      tag: 'defaultedThunk',
23543
      process: fallbackThunk
23544
    });
23545
    const defaulted$1 = fallback => defaultedThunk(constant(fallback));
23546
    const asOption = () => ({
23547
      tag: 'option',
23548
      process: {}
23549
    });
23550
 
23551
    const mergeValues = (values, base) => values.length > 0 ? SimpleResult.svalue(deepMerge(base, merge.apply(undefined, values))) : SimpleResult.svalue(base);
23552
    const mergeErrors = errors => compose(SimpleResult.serror, flatten)(errors);
23553
    const consolidateObj = (objects, base) => {
23554
      const partition = SimpleResult.partition(objects);
23555
      return partition.errors.length > 0 ? mergeErrors(partition.errors) : mergeValues(partition.values, base);
23556
    };
23557
    const consolidateArr = objects => {
23558
      const partitions = SimpleResult.partition(objects);
23559
      return partitions.errors.length > 0 ? mergeErrors(partitions.errors) : SimpleResult.svalue(partitions.values);
23560
    };
23561
    const ResultCombine = {
23562
      consolidateObj,
23563
      consolidateArr
23564
    };
23565
 
23566
    const field$1 = (key, newKey, presence, prop) => ({
23567
      tag: 'field',
23568
      key,
23569
      newKey,
23570
      presence,
23571
      prop
23572
    });
23573
    const customField$1 = (newKey, instantiator) => ({
23574
      tag: 'custom',
23575
      newKey,
23576
      instantiator
23577
    });
23578
    const fold = (value, ifField, ifCustom) => {
23579
      switch (value.tag) {
23580
      case 'field':
23581
        return ifField(value.key, value.newKey, value.presence, value.prop);
23582
      case 'custom':
23583
        return ifCustom(value.newKey, value.instantiator);
23584
      }
23585
    };
23586
 
23587
    const value = validator => {
23588
      const extract = (path, val) => {
23589
        return SimpleResult.bindError(validator(val), err => custom(path, err));
23590
      };
23591
      const toString = constant('val');
23592
      return {
23593
        extract,
23594
        toString
23595
      };
23596
    };
23597
    const anyValue$1 = value(SimpleResult.svalue);
23598
 
23599
    const requiredAccess = (path, obj, key, bundle) => get$a(obj, key).fold(() => missingRequired(path, key, obj), bundle);
23600
    const fallbackAccess = (obj, key, fallback, bundle) => {
23601
      const v = get$a(obj, key).getOrThunk(() => fallback(obj));
23602
      return bundle(v);
23603
    };
23604
    const optionAccess = (obj, key, bundle) => bundle(get$a(obj, key));
23605
    const optionDefaultedAccess = (obj, key, fallback, bundle) => {
23606
      const opt = get$a(obj, key).map(val => val === true ? fallback(obj) : val);
23607
      return bundle(opt);
23608
    };
23609
    const extractField = (field, path, obj, key, prop) => {
23610
      const bundle = av => prop.extract(path.concat([key]), av);
23611
      const bundleAsOption = optValue => optValue.fold(() => SimpleResult.svalue(Optional.none()), ov => {
23612
        const result = prop.extract(path.concat([key]), ov);
23613
        return SimpleResult.map(result, Optional.some);
23614
      });
23615
      switch (field.tag) {
23616
      case 'required':
23617
        return requiredAccess(path, obj, key, bundle);
23618
      case 'defaultedThunk':
23619
        return fallbackAccess(obj, key, field.process, bundle);
23620
      case 'option':
23621
        return optionAccess(obj, key, bundleAsOption);
23622
      case 'defaultedOptionThunk':
23623
        return optionDefaultedAccess(obj, key, field.process, bundleAsOption);
23624
      case 'mergeWithThunk': {
23625
          return fallbackAccess(obj, key, constant({}), v => {
23626
            const result = deepMerge(field.process(obj), v);
23627
            return bundle(result);
23628
          });
23629
        }
23630
      }
23631
    };
23632
    const extractFields = (path, obj, fields) => {
23633
      const success = {};
23634
      const errors = [];
23635
      for (const field of fields) {
23636
        fold(field, (key, newKey, presence, prop) => {
23637
          const result = extractField(presence, path, obj, key, prop);
23638
          SimpleResult.fold(result, err => {
23639
            errors.push(...err);
23640
          }, res => {
23641
            success[newKey] = res;
23642
          });
23643
        }, (newKey, instantiator) => {
23644
          success[newKey] = instantiator(obj);
23645
        });
23646
      }
23647
      return errors.length > 0 ? SimpleResult.serror(errors) : SimpleResult.svalue(success);
23648
    };
23649
    const objOf = values => {
23650
      const extract = (path, o) => extractFields(path, o, values);
23651
      const toString = () => {
23652
        const fieldStrings = map$3(values, value => fold(value, (key, _okey, _presence, prop) => key + ' -> ' + prop.toString(), (newKey, _instantiator) => 'state(' + newKey + ')'));
23653
        return 'obj{\n' + fieldStrings.join('\n') + '}';
23654
      };
23655
      return {
23656
        extract,
23657
        toString
23658
      };
23659
    };
23660
    const arrOf = prop => {
23661
      const extract = (path, array) => {
23662
        const results = map$3(array, (a, i) => prop.extract(path.concat(['[' + i + ']']), a));
23663
        return ResultCombine.consolidateArr(results);
23664
      };
23665
      const toString = () => 'array(' + prop.toString() + ')';
23666
      return {
23667
        extract,
23668
        toString
23669
      };
23670
    };
23671
 
23672
    const valueOf = validator => value(v => validator(v).fold(SimpleResult.serror, SimpleResult.svalue));
23673
    const extractValue = (label, prop, obj) => {
23674
      const res = prop.extract([label], obj);
23675
      return SimpleResult.mapError(res, errs => ({
23676
        input: obj,
23677
        errors: errs
23678
      }));
23679
    };
23680
    const asRaw = (label, prop, obj) => SimpleResult.toResult(extractValue(label, prop, obj));
23681
    const formatError = errInfo => {
23682
      return 'Errors: \n' + formatErrors(errInfo.errors).join('\n') + '\n\nInput object: ' + formatObj(errInfo.input);
23683
    };
23684
    const choose = (key, branches) => choose$1(key, map$2(branches, objOf));
23685
 
23686
    const anyValue = constant(anyValue$1);
23687
    const typedValue = (validator, expectedType) => value(a => {
23688
      const actualType = typeof a;
23689
      return validator(a) ? SimpleResult.svalue(a) : SimpleResult.serror(`Expected type: ${ expectedType } but got: ${ actualType }`);
23690
    });
23691
    const number = typedValue(isNumber, 'number');
23692
    const string = typedValue(isString, 'string');
23693
    const boolean = typedValue(isBoolean, 'boolean');
23694
    const functionProcessor = typedValue(isFunction, 'function');
23695
 
23696
    const field = field$1;
23697
    const customField = customField$1;
23698
    const validateEnum = values => valueOf(value => contains$2(values, value) ? Result.value(value) : Result.error(`Unsupported value: "${ value }", choose one of "${ values.join(', ') }".`));
23699
    const requiredOf = (key, schema) => field(key, key, required(), schema);
23700
    const requiredString = key => requiredOf(key, string);
23701
    const requiredFunction = key => requiredOf(key, functionProcessor);
23702
    const requiredArrayOf = (key, schema) => field(key, key, required(), arrOf(schema));
23703
    const optionOf = (key, schema) => field(key, key, asOption(), schema);
23704
    const optionString = key => optionOf(key, string);
23705
    const optionFunction = key => optionOf(key, functionProcessor);
23706
    const defaulted = (key, fallback) => field(key, key, defaulted$1(fallback), anyValue());
23707
    const defaultedOf = (key, fallback, schema) => field(key, key, defaulted$1(fallback), schema);
23708
    const defaultedNumber = (key, fallback) => defaultedOf(key, fallback, number);
23709
    const defaultedString = (key, fallback) => defaultedOf(key, fallback, string);
23710
    const defaultedStringEnum = (key, fallback, values) => defaultedOf(key, fallback, validateEnum(values));
23711
    const defaultedBoolean = (key, fallback) => defaultedOf(key, fallback, boolean);
23712
    const defaultedFunction = (key, fallback) => defaultedOf(key, fallback, functionProcessor);
23713
    const defaultedArrayOf = (key, fallback, schema) => defaultedOf(key, fallback, arrOf(schema));
23714
 
23715
    const type = requiredString('type');
23716
    const fetch$1 = requiredFunction('fetch');
23717
    const onAction = requiredFunction('onAction');
23718
    const onSetup = defaultedFunction('onSetup', () => noop);
23719
    const optionalText = optionString('text');
23720
    const optionalIcon = optionString('icon');
23721
    const optionalTooltip = optionString('tooltip');
23722
    const optionalLabel = optionString('label');
23723
    const active = defaultedBoolean('active', false);
23724
    const enabled = defaultedBoolean('enabled', true);
23725
    const primary = defaultedBoolean('primary', false);
23726
    const defaultedColumns = num => defaulted('columns', num);
23727
    const defaultedType = type => defaultedString('type', type);
23728
 
23729
    const autocompleterSchema = objOf([
23730
      type,
23731
      requiredString('trigger'),
23732
      defaultedNumber('minChars', 1),
23733
      defaultedColumns(1),
23734
      defaultedNumber('maxResults', 10),
23735
      optionFunction('matches'),
23736
      fetch$1,
23737
      onAction,
23738
      defaultedArrayOf('highlightOn', [], string)
23739
    ]);
23740
    const createAutocompleter = spec => asRaw('Autocompleter', autocompleterSchema, {
23741
      trigger: spec.ch,
23742
      ...spec
23743
    });
23744
 
23745
    const baseToolbarButtonFields = [
23746
      enabled,
23747
      optionalTooltip,
23748
      optionalIcon,
23749
      optionalText,
23750
      onSetup
23751
    ];
23752
 
23753
    const baseToolbarToggleButtonFields = [active].concat(baseToolbarButtonFields);
23754
 
23755
    const contextBarFields = [
23756
      defaultedFunction('predicate', never),
23757
      defaultedStringEnum('scope', 'node', [
23758
        'node',
23759
        'editor'
23760
      ]),
23761
      defaultedStringEnum('position', 'selection', [
23762
        'node',
23763
        'selection',
23764
        'line'
23765
      ])
23766
    ];
23767
 
23768
    const contextButtonFields = baseToolbarButtonFields.concat([
23769
      defaultedType('contextformbutton'),
23770
      primary,
23771
      onAction,
23772
      customField('original', identity)
23773
    ]);
23774
    const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([
23775
      defaultedType('contextformbutton'),
23776
      primary,
23777
      onAction,
23778
      customField('original', identity)
23779
    ]);
23780
    const launchButtonFields = baseToolbarButtonFields.concat([defaultedType('contextformbutton')]);
23781
    const launchToggleButtonFields = baseToolbarToggleButtonFields.concat([defaultedType('contextformtogglebutton')]);
23782
    const toggleOrNormal = choose('type', {
23783
      contextformbutton: contextButtonFields,
23784
      contextformtogglebutton: contextToggleButtonFields
23785
    });
23786
    objOf([
23787
      defaultedType('contextform'),
23788
      defaultedFunction('initValue', constant('')),
23789
      optionalLabel,
23790
      requiredArrayOf('commands', toggleOrNormal),
23791
      optionOf('launch', choose('type', {
23792
        contextformbutton: launchButtonFields,
23793
        contextformtogglebutton: launchToggleButtonFields
23794
      }))
23795
    ].concat(contextBarFields));
23796
 
23797
    const register$2 = editor => {
23798
      const popups = editor.ui.registry.getAll().popups;
23799
      const dataset = map$2(popups, popup => createAutocompleter(popup).fold(err => {
23800
        throw new Error(formatError(err));
23801
      }, identity));
23802
      const triggers = stringArray(mapToArray(dataset, v => v.trigger));
23803
      const datasetValues = values(dataset);
23804
      const lookupByTrigger = trigger => filter$5(datasetValues, dv => dv.trigger === trigger);
23805
      return {
23806
        dataset,
23807
        triggers,
23808
        lookupByTrigger
23809
      };
23810
    };
23811
 
23812
    const setupEditorInput = (editor, api) => {
23813
      const update = last$1(api.load, 50);
23814
      editor.on('keypress compositionend', e => {
23815
        if (e.which === 27) {
23816
          return;
23817
        }
23818
        update.throttle();
23819
      });
23820
      editor.on('keydown', e => {
23821
        const keyCode = e.which;
23822
        if (keyCode === 8) {
23823
          update.throttle();
23824
        } else if (keyCode === 27) {
23825
          api.cancelIfNecessary();
23826
        }
23827
      });
23828
      editor.on('remove', update.cancel);
23829
    };
23830
    const setup$k = editor => {
23831
      const activeAutocompleter = value$2();
23832
      const uiActive = Cell(false);
23833
      const isActive = activeAutocompleter.isSet;
23834
      const cancelIfNecessary = () => {
23835
        if (isActive()) {
23836
          removeAutocompleterDecoration(editor);
23837
          fireAutocompleterEnd(editor);
23838
          uiActive.set(false);
23839
          activeAutocompleter.clear();
23840
        }
23841
      };
23842
      const commenceIfNecessary = context => {
23843
        if (!isActive()) {
23844
          addAutocompleterDecoration(editor, context.range);
23845
          activeAutocompleter.set({
23846
            trigger: context.trigger,
23847
            matchLength: context.text.length
23848
          });
23849
        }
23850
      };
23851
      const getAutocompleters = cached(() => register$2(editor));
23852
      const doLookup = fetchOptions => activeAutocompleter.get().map(ac => getContext(editor.dom, editor.selection.getRng(), ac.trigger).bind(newContext => lookupWithContext(editor, getAutocompleters, newContext, fetchOptions))).getOrThunk(() => lookup(editor, getAutocompleters));
23853
      const load = fetchOptions => {
23854
        doLookup(fetchOptions).fold(cancelIfNecessary, lookupInfo => {
23855
          commenceIfNecessary(lookupInfo.context);
23856
          lookupInfo.lookupData.then(lookupData => {
23857
            activeAutocompleter.get().map(ac => {
23858
              const context = lookupInfo.context;
23859
              if (ac.trigger === context.trigger) {
23860
                if (context.text.length - ac.matchLength >= 10) {
23861
                  cancelIfNecessary();
23862
                } else {
23863
                  activeAutocompleter.set({
23864
                    ...ac,
23865
                    matchLength: context.text.length
23866
                  });
23867
                  if (uiActive.get()) {
23868
                    fireAutocompleterUpdate(editor, { lookupData });
23869
                  } else {
23870
                    uiActive.set(true);
23871
                    fireAutocompleterStart(editor, { lookupData });
23872
                  }
23873
                }
23874
              }
23875
            });
23876
          });
23877
        });
23878
      };
23879
      editor.addCommand('mceAutocompleterReload', (_ui, value) => {
23880
        const fetchOptions = isObject(value) ? value.fetchOptions : {};
23881
        load(fetchOptions);
23882
      });
23883
      editor.addCommand('mceAutocompleterClose', cancelIfNecessary);
23884
      setupEditorInput(editor, {
23885
        cancelIfNecessary,
23886
        load
23887
      });
23888
    };
23889
 
23890
    const browser$1 = detect$2().browser;
23891
    const isSafari = browser$1.isSafari();
23892
    const emptyNodeContents = node => fillWithPaddingBr(SugarElement.fromDom(node));
23893
    const isEntireNodeSelected = (rng, node) => {
23894
      var _a;
23895
      return rng.startOffset === 0 && rng.endOffset === ((_a = node.textContent) === null || _a === void 0 ? void 0 : _a.length);
23896
    };
23897
    const getParentDetailsElementAtPos = (dom, pos) => Optional.from(dom.getParent(pos.container(), 'details'));
23898
    const isInDetailsElement = (dom, pos) => getParentDetailsElementAtPos(dom, pos).isSome();
23899
    const getDetailsElements = (dom, rng) => {
23900
      const startDetails = Optional.from(dom.getParent(rng.startContainer, 'details'));
23901
      const endDetails = Optional.from(dom.getParent(rng.endContainer, 'details'));
23902
      if (startDetails.isSome() || endDetails.isSome()) {
23903
        const startSummary = startDetails.bind(details => Optional.from(dom.select('summary', details)[0]));
23904
        return Optional.some({
23905
          startSummary,
23906
          startDetails,
23907
          endDetails
23908
        });
23909
      } else {
23910
        return Optional.none();
23911
      }
23912
    };
23913
    const isCaretInTheBeginningOf = (caretPos, element) => firstPositionIn(element).exists(pos => pos.isEqual(caretPos));
23914
    const isCaretInTheEndOf = (caretPos, element) => {
23915
      return lastPositionIn(element).exists(pos => {
23916
        if (isBr$6(pos.getNode())) {
23917
          return prevPosition(element, pos).exists(pos2 => pos2.isEqual(caretPos)) || pos.isEqual(caretPos);
23918
        } else {
23919
          return pos.isEqual(caretPos);
23920
        }
23921
      });
23922
    };
23923
    const isCaretAtStartOfSummary = (caretPos, detailsElements) => detailsElements.startSummary.exists(summary => isCaretInTheBeginningOf(caretPos, summary));
23924
    const isCaretAtEndOfSummary = (caretPos, detailsElements) => detailsElements.startSummary.exists(summary => isCaretInTheEndOf(caretPos, summary));
23925
    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()))));
23926
    const isCaretInLastPositionInBody = (root, caretPos, detailsElements) => detailsElements.startDetails.exists(details => nextPosition(root, caretPos).forall(pos => !details.contains(pos.container())));
23927
    const setCaretToPosition = (editor, position) => {
23928
      const node = position.getNode();
23929
      if (!isUndefined(node)) {
23930
        editor.selection.setCursorLocation(node, position.offset());
23931
      }
23932
    };
23933
    const moveCaretToDetailsPos = (editor, pos, forward) => {
23934
      const details = editor.dom.getParent(pos.container(), 'details');
23935
      if (details && !details.open) {
23936
        const summary = editor.dom.select('summary', details)[0];
23937
        if (summary) {
23938
          const newPos = forward ? firstPositionIn(summary) : lastPositionIn(summary);
23939
          newPos.each(pos => setCaretToPosition(editor, pos));
23940
        }
23941
      } else {
23942
        setCaretToPosition(editor, pos);
23943
      }
23944
    };
23945
    const isPartialDelete = (rng, detailsElements) => {
23946
      const containsStart = element => element.contains(rng.startContainer);
23947
      const containsEnd = element => element.contains(rng.endContainer);
23948
      const startInSummary = detailsElements.startSummary.exists(containsStart);
23949
      const endInSummary = detailsElements.startSummary.exists(containsEnd);
23950
      const isPartiallySelectedDetailsElements = detailsElements.startDetails.forall(startDetails => detailsElements.endDetails.forall(endDetails => startDetails !== endDetails));
23951
      const isInPartiallySelectedSummary = (startInSummary || endInSummary) && !(startInSummary && endInSummary);
23952
      return isInPartiallySelectedSummary || isPartiallySelectedDetailsElements;
23953
    };
23954
    const shouldPreventDeleteIntoDetails = (editor, forward, granularity) => {
23955
      const {dom, selection} = editor;
23956
      const root = editor.getBody();
23957
      if (granularity === 'character') {
23958
        const caretPos = CaretPosition.fromRangeStart(selection.getRng());
23959
        const parentBlock = dom.getParent(caretPos.container(), dom.isBlock);
23960
        const parentDetailsAtCaret = getParentDetailsElementAtPos(dom, caretPos);
23961
        const inEmptyParentBlock = parentBlock && dom.isEmpty(parentBlock);
23962
        const isFirstBlock = isNull(parentBlock === null || parentBlock === void 0 ? void 0 : parentBlock.previousSibling);
23963
        const isLastBlock = isNull(parentBlock === null || parentBlock === void 0 ? void 0 : parentBlock.nextSibling);
23964
        if (inEmptyParentBlock) {
23965
          const firstOrLast = forward ? isLastBlock : isFirstBlock;
23966
          if (firstOrLast) {
23967
            const isBeforeAfterDetails = navigate(!forward, root, caretPos).exists(pos => {
23968
              return isInDetailsElement(dom, pos) && !equals(parentDetailsAtCaret, getParentDetailsElementAtPos(dom, pos));
23969
            });
23970
            if (isBeforeAfterDetails) {
23971
              return true;
23972
            }
23973
          }
23974
        }
23975
        return navigate(forward, root, caretPos).fold(never, pos => {
23976
          const parentDetailsAtNewPos = getParentDetailsElementAtPos(dom, pos);
23977
          if (isInDetailsElement(dom, pos) && !equals(parentDetailsAtCaret, parentDetailsAtNewPos)) {
23978
            if (!forward) {
23979
              moveCaretToDetailsPos(editor, pos, false);
23980
            }
23981
            if (parentBlock && inEmptyParentBlock) {
23982
              if (forward && isFirstBlock) {
23983
                return true;
23984
              } else if (!forward && isLastBlock) {
23985
                return true;
23986
              }
23987
              moveCaretToDetailsPos(editor, pos, forward);
23988
              editor.dom.remove(parentBlock);
23989
            }
23990
            return true;
23991
          } else {
23992
            return false;
23993
          }
23994
        });
23995
      } else {
23996
        return false;
23997
      }
23998
    };
23999
    const shouldPreventDeleteSummaryAction = (editor, detailElements, forward, granularity) => {
24000
      const selection = editor.selection;
24001
      const rng = selection.getRng();
24002
      const caretPos = CaretPosition.fromRangeStart(rng);
24003
      const root = editor.getBody();
24004
      if (granularity === 'selection') {
24005
        return isPartialDelete(rng, detailElements);
24006
      } else if (forward) {
24007
        return isCaretAtEndOfSummary(caretPos, detailElements) || isCaretInLastPositionInBody(root, caretPos, detailElements);
24008
      } else {
24009
        return isCaretAtStartOfSummary(caretPos, detailElements) || isCaretInFirstPositionInBody(caretPos, detailElements);
24010
      }
24011
    };
24012
    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));
24013
    const handleDeleteActionSafari = (editor, forward, granularity) => {
24014
      const selection = editor.selection;
24015
      const node = selection.getNode();
24016
      const rng = selection.getRng();
24017
      const caretPos = CaretPosition.fromRangeStart(rng);
24018
      if (isSummary$1(node)) {
24019
        if (granularity === 'selection' && isEntireNodeSelected(rng, node) || willDeleteLastPositionInElement(forward, caretPos, node)) {
24020
          emptyNodeContents(node);
24021
        } else {
24022
          editor.undoManager.transact(() => {
24023
            const sel = selection.getSel();
24024
            let {anchorNode, anchorOffset, focusNode, focusOffset} = sel !== null && sel !== void 0 ? sel : {};
24025
            const applySelection = () => {
24026
              if (isNonNullable(anchorNode) && isNonNullable(anchorOffset) && isNonNullable(focusNode) && isNonNullable(focusOffset)) {
24027
                sel === null || sel === void 0 ? void 0 : sel.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
24028
              }
24029
            };
24030
            const updateSelection = () => {
24031
              anchorNode = sel === null || sel === void 0 ? void 0 : sel.anchorNode;
24032
              anchorOffset = sel === null || sel === void 0 ? void 0 : sel.anchorOffset;
24033
              focusNode = sel === null || sel === void 0 ? void 0 : sel.focusNode;
24034
              focusOffset = sel === null || sel === void 0 ? void 0 : sel.focusOffset;
24035
            };
24036
            const appendAllChildNodes = (from, to) => {
24037
              each$e(from.childNodes, child => {
24038
                if (isNode(child)) {
24039
                  to.appendChild(child);
24040
                }
24041
              });
24042
            };
24043
            const container = editor.dom.create('span', { 'data-mce-bogus': '1' });
24044
            appendAllChildNodes(node, container);
24045
            node.appendChild(container);
24046
            applySelection();
24047
            if (granularity === 'word' || granularity === 'line') {
24048
              sel === null || sel === void 0 ? void 0 : sel.modify('extend', forward ? 'right' : 'left', granularity);
24049
            }
24050
            if (!selection.isCollapsed() && isEntireNodeSelected(selection.getRng(), container)) {
24051
              emptyNodeContents(node);
24052
            } else {
24053
              editor.execCommand(forward ? 'ForwardDelete' : 'Delete');
24054
              updateSelection();
24055
              appendAllChildNodes(container, node);
24056
              applySelection();
24057
            }
24058
            editor.dom.remove(container);
24059
          });
24060
        }
24061
        return true;
24062
      } else {
24063
        return false;
24064
      }
24065
    };
24066
    const backspaceDelete = (editor, forward, granularity) => shouldPreventDeleteAction(editor, forward, granularity) || isSafari && handleDeleteActionSafari(editor, forward, granularity) ? Optional.some(noop) : Optional.none();
24067
 
24068
    const createAndFireInputEvent = eventType => (editor, inputType, specifics = {}) => {
24069
      const target = editor.getBody();
24070
      const overrides = {
24071
        bubbles: true,
24072
        composed: true,
24073
        data: null,
24074
        isComposing: false,
24075
        detail: 0,
24076
        view: null,
24077
        target,
24078
        currentTarget: target,
24079
        eventPhase: Event.AT_TARGET,
24080
        originalTarget: target,
24081
        explicitOriginalTarget: target,
24082
        isTrusted: false,
24083
        srcElement: target,
24084
        cancelable: false,
24085
        preventDefault: noop,
24086
        inputType
24087
      };
24088
      const input = clone$3(new InputEvent(eventType));
24089
      return editor.dispatch(eventType, {
24090
        ...input,
24091
        ...overrides,
24092
        ...specifics
24093
      });
24094
    };
24095
    const fireInputEvent = createAndFireInputEvent('input');
24096
    const fireBeforeInputEvent = createAndFireInputEvent('beforeinput');
24097
 
24098
    const platform$2 = detect$2();
24099
    const os = platform$2.os;
24100
    const isMacOSOriOS = os.isMacOS() || os.isiOS();
24101
    const browser = platform$2.browser;
24102
    const isFirefox = browser.isFirefox();
24103
    const executeKeydownOverride$3 = (editor, caret, evt) => {
24104
      const inputType = evt.keyCode === VK.BACKSPACE ? 'deleteContentBackward' : 'deleteContentForward';
24105
      const isCollapsed = editor.selection.isCollapsed();
24106
      const unmodifiedGranularity = isCollapsed ? 'character' : 'selection';
24107
      const getModifiedGranularity = isWord => {
24108
        if (isCollapsed) {
24109
          return isWord ? 'word' : 'line';
24110
        } else {
24111
          return 'selection';
24112
        }
24113
      };
24114
      executeWithDelayedAction([
24115
        {
24116
          keyCode: VK.BACKSPACE,
24117
          action: action(backspaceDelete$1, editor)
24118
        },
24119
        {
24120
          keyCode: VK.BACKSPACE,
24121
          action: action(backspaceDelete$6, editor, false)
24122
        },
24123
        {
24124
          keyCode: VK.DELETE,
24125
          action: action(backspaceDelete$6, editor, true)
24126
        },
24127
        {
24128
          keyCode: VK.BACKSPACE,
24129
          action: action(backspaceDelete$7, editor, false)
24130
        },
24131
        {
24132
          keyCode: VK.DELETE,
24133
          action: action(backspaceDelete$7, editor, true)
24134
        },
24135
        {
24136
          keyCode: VK.BACKSPACE,
24137
          action: action(backspaceDelete$4, editor, caret, false)
24138
        },
24139
        {
24140
          keyCode: VK.DELETE,
24141
          action: action(backspaceDelete$4, editor, caret, true)
24142
        },
24143
        {
24144
          keyCode: VK.BACKSPACE,
24145
          action: action(backspaceDelete$a, editor, false)
24146
        },
24147
        {
24148
          keyCode: VK.DELETE,
24149
          action: action(backspaceDelete$a, editor, true)
24150
        },
24151
        {
24152
          keyCode: VK.BACKSPACE,
24153
          action: action(backspaceDelete, editor, false, unmodifiedGranularity)
24154
        },
24155
        {
24156
          keyCode: VK.DELETE,
24157
          action: action(backspaceDelete, editor, true, unmodifiedGranularity)
24158
        },
24159
        ...isMacOSOriOS ? [
24160
          {
24161
            keyCode: VK.BACKSPACE,
24162
            altKey: true,
24163
            action: action(backspaceDelete, editor, false, getModifiedGranularity(true))
24164
          },
24165
          {
24166
            keyCode: VK.DELETE,
24167
            altKey: true,
24168
            action: action(backspaceDelete, editor, true, getModifiedGranularity(true))
24169
          },
24170
          {
24171
            keyCode: VK.BACKSPACE,
24172
            metaKey: true,
24173
            action: action(backspaceDelete, editor, false, getModifiedGranularity(false))
24174
          }
24175
        ] : [
24176
          {
24177
            keyCode: VK.BACKSPACE,
24178
            ctrlKey: true,
24179
            action: action(backspaceDelete, editor, false, getModifiedGranularity(true))
24180
          },
24181
          {
24182
            keyCode: VK.DELETE,
24183
            ctrlKey: true,
24184
            action: action(backspaceDelete, editor, true, getModifiedGranularity(true))
24185
          }
24186
        ],
24187
        {
24188
          keyCode: VK.BACKSPACE,
24189
          action: action(backspaceDelete$5, editor, false)
24190
        },
24191
        {
24192
          keyCode: VK.DELETE,
24193
          action: action(backspaceDelete$5, editor, true)
24194
        },
24195
        {
24196
          keyCode: VK.BACKSPACE,
24197
          action: action(backspaceDelete$2, editor, false)
24198
        },
24199
        {
24200
          keyCode: VK.DELETE,
24201
          action: action(backspaceDelete$2, editor, true)
24202
        },
24203
        {
24204
          keyCode: VK.BACKSPACE,
24205
          action: action(backspaceDelete$8, editor, false)
24206
        },
24207
        {
24208
          keyCode: VK.DELETE,
24209
          action: action(backspaceDelete$8, editor, true)
24210
        },
24211
        {
24212
          keyCode: VK.BACKSPACE,
24213
          action: action(backspaceDelete$9, editor, false)
24214
        },
24215
        {
24216
          keyCode: VK.DELETE,
24217
          action: action(backspaceDelete$9, editor, true)
24218
        },
24219
        {
24220
          keyCode: VK.BACKSPACE,
24221
          action: action(backspaceDelete$3, editor, false)
24222
        },
24223
        {
24224
          keyCode: VK.DELETE,
24225
          action: action(backspaceDelete$3, editor, true)
24226
        }
24227
      ], evt).filter(_ => editor.selection.isEditable()).each(applyAction => {
24228
        evt.preventDefault();
24229
        const beforeInput = fireBeforeInputEvent(editor, inputType);
24230
        if (!beforeInput.isDefaultPrevented()) {
24231
          applyAction();
24232
          fireInputEvent(editor, inputType);
24233
        }
24234
      });
24235
    };
24236
    const executeKeyupOverride = (editor, evt, isBackspaceKeydown) => execute([
24237
      {
24238
        keyCode: VK.BACKSPACE,
24239
        action: action(paddEmptyElement, editor)
24240
      },
24241
      {
24242
        keyCode: VK.DELETE,
24243
        action: action(paddEmptyElement, editor)
24244
      },
24245
      ...isMacOSOriOS ? [
24246
        {
24247
          keyCode: VK.BACKSPACE,
24248
          altKey: true,
24249
          action: action(refreshCaret, editor)
24250
        },
24251
        {
24252
          keyCode: VK.DELETE,
24253
          altKey: true,
24254
          action: action(refreshCaret, editor)
24255
        },
24256
        ...isBackspaceKeydown ? [{
24257
            keyCode: isFirefox ? 224 : 91,
24258
            action: action(refreshCaret, editor)
24259
          }] : []
24260
      ] : [
24261
        {
24262
          keyCode: VK.BACKSPACE,
24263
          ctrlKey: true,
24264
          action: action(refreshCaret, editor)
24265
        },
24266
        {
24267
          keyCode: VK.DELETE,
24268
          ctrlKey: true,
24269
          action: action(refreshCaret, editor)
24270
        }
24271
      ]
24272
    ], evt);
24273
    const setup$j = (editor, caret) => {
24274
      let isBackspaceKeydown = false;
24275
      editor.on('keydown', evt => {
24276
        isBackspaceKeydown = evt.keyCode === VK.BACKSPACE;
24277
        if (!evt.isDefaultPrevented()) {
24278
          executeKeydownOverride$3(editor, caret, evt);
24279
        }
24280
      });
24281
      editor.on('keyup', evt => {
24282
        if (!evt.isDefaultPrevented()) {
24283
          executeKeyupOverride(editor, evt, isBackspaceKeydown);
24284
        }
24285
        isBackspaceKeydown = false;
24286
      });
24287
    };
24288
 
24289
    const firstNonWhiteSpaceNodeSibling = node => {
24290
      while (node) {
24291
        if (isElement$6(node) || isText$a(node) && node.data && /[\r\n\s]/.test(node.data)) {
24292
          return node;
24293
        }
24294
        node = node.nextSibling;
24295
      }
24296
      return null;
24297
    };
24298
    const moveToCaretPosition = (editor, root) => {
24299
      const dom = editor.dom;
24300
      const moveCaretBeforeOnEnterElementsMap = editor.schema.getMoveCaretBeforeOnEnterElements();
24301
      if (!root) {
24302
        return;
24303
      }
24304
      if (/^(LI|DT|DD)$/.test(root.nodeName)) {
24305
        const firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
24306
        if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) {
24307
          root.insertBefore(dom.doc.createTextNode(nbsp), root.firstChild);
24308
        }
24309
      }
24310
      const rng = dom.createRng();
24311
      root.normalize();
24312
      if (root.hasChildNodes()) {
24313
        const walker = new DomTreeWalker(root, root);
24314
        let lastNode = root;
24315
        let node;
24316
        while (node = walker.current()) {
24317
          if (isText$a(node)) {
24318
            rng.setStart(node, 0);
24319
            rng.setEnd(node, 0);
24320
            break;
24321
          }
24322
          if (moveCaretBeforeOnEnterElementsMap[node.nodeName.toLowerCase()]) {
24323
            rng.setStartBefore(node);
24324
            rng.setEndBefore(node);
24325
            break;
24326
          }
24327
          lastNode = node;
24328
          node = walker.next();
24329
        }
24330
        if (!node) {
24331
          rng.setStart(lastNode, 0);
24332
          rng.setEnd(lastNode, 0);
24333
        }
24334
      } else {
24335
        if (isBr$6(root)) {
24336
          if (root.nextSibling && dom.isBlock(root.nextSibling)) {
24337
            rng.setStartBefore(root);
24338
            rng.setEndBefore(root);
24339
          } else {
24340
            rng.setStartAfter(root);
24341
            rng.setEndAfter(root);
24342
          }
24343
        } else {
24344
          rng.setStart(root, 0);
24345
          rng.setEnd(root, 0);
24346
        }
24347
      }
24348
      editor.selection.setRng(rng);
24349
      scrollRangeIntoView(editor, rng);
24350
    };
24351
    const getEditableRoot = (dom, node) => {
24352
      const root = dom.getRoot();
24353
      let editableRoot;
24354
      let parent = node;
24355
      while (parent !== root && parent && dom.getContentEditable(parent) !== 'false') {
24356
        if (dom.getContentEditable(parent) === 'true') {
24357
          editableRoot = parent;
24358
          break;
24359
        }
24360
        parent = parent.parentNode;
24361
      }
24362
      return parent !== root ? editableRoot : root;
24363
    };
24364
    const getParentBlock$1 = editor => {
24365
      return Optional.from(editor.dom.getParent(editor.selection.getStart(true), editor.dom.isBlock));
24366
    };
24367
    const getParentBlockName = editor => {
24368
      return getParentBlock$1(editor).fold(constant(''), parentBlock => {
24369
        return parentBlock.nodeName.toUpperCase();
24370
      });
24371
    };
24372
    const isListItemParentBlock = editor => {
24373
      return getParentBlock$1(editor).filter(elm => {
24374
        return isListItem$1(SugarElement.fromDom(elm));
24375
      }).isSome();
24376
    };
24377
    const emptyBlock = elm => {
24378
      elm.innerHTML = '<br data-mce-bogus="1">';
24379
    };
24380
    const applyAttributes = (editor, node, forcedRootBlockAttrs) => {
24381
      const dom = editor.dom;
24382
      Optional.from(forcedRootBlockAttrs.style).map(dom.parseStyle).each(attrStyles => {
24383
        const currentStyles = getAllRaw(SugarElement.fromDom(node));
24384
        const newStyles = {
24385
          ...currentStyles,
24386
          ...attrStyles
24387
        };
24388
        dom.setStyles(node, newStyles);
24389
      });
24390
      const attrClassesOpt = Optional.from(forcedRootBlockAttrs.class).map(attrClasses => attrClasses.split(/\s+/));
24391
      const currentClassesOpt = Optional.from(node.className).map(currentClasses => filter$5(currentClasses.split(/\s+/), clazz => clazz !== ''));
24392
      lift2(attrClassesOpt, currentClassesOpt, (attrClasses, currentClasses) => {
24393
        const filteredClasses = filter$5(currentClasses, clazz => !contains$2(attrClasses, clazz));
24394
        const newClasses = [
24395
          ...attrClasses,
24396
          ...filteredClasses
24397
        ];
24398
        dom.setAttrib(node, 'class', newClasses.join(' '));
24399
      });
24400
      const appliedAttrs = [
24401
        'style',
24402
        'class'
24403
      ];
24404
      const remainingAttrs = filter$4(forcedRootBlockAttrs, (_, attrs) => !contains$2(appliedAttrs, attrs));
24405
      dom.setAttribs(node, remainingAttrs);
24406
    };
24407
    const setForcedBlockAttrs = (editor, node) => {
24408
      const forcedRootBlockName = getForcedRootBlock(editor);
24409
      if (forcedRootBlockName.toLowerCase() === node.tagName.toLowerCase()) {
24410
        const forcedRootBlockAttrs = getForcedRootBlockAttrs(editor);
24411
        applyAttributes(editor, node, forcedRootBlockAttrs);
24412
      }
24413
    };
24414
    const createNewBlock = (editor, container, parentBlock, editableRoot, keepStyles = true, name, styles) => {
24415
      const dom = editor.dom;
24416
      const schema = editor.schema;
24417
      const newBlockName = getForcedRootBlock(editor);
24418
      const parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : '';
24419
      let node = container;
24420
      const textInlineElements = schema.getTextInlineElements();
24421
      let block;
24422
      if (name || parentBlockName === 'TABLE' || parentBlockName === 'HR') {
24423
        block = dom.create(name || newBlockName, styles || {});
24424
      } else {
24425
        block = parentBlock.cloneNode(false);
24426
      }
24427
      let caretNode = block;
24428
      if (!keepStyles) {
24429
        dom.setAttrib(block, 'style', null);
24430
        dom.setAttrib(block, 'class', null);
24431
      } else {
24432
        do {
24433
          if (textInlineElements[node.nodeName]) {
24434
            if (isCaretNode(node) || isBookmarkNode$1(node)) {
24435
              continue;
24436
            }
24437
            const clonedNode = node.cloneNode(false);
24438
            dom.setAttrib(clonedNode, 'id', '');
24439
            if (block.hasChildNodes()) {
24440
              clonedNode.appendChild(block.firstChild);
24441
              block.appendChild(clonedNode);
24442
            } else {
24443
              caretNode = clonedNode;
24444
              block.appendChild(clonedNode);
24445
            }
24446
          }
24447
        } while ((node = node.parentNode) && node !== editableRoot);
24448
      }
24449
      setForcedBlockAttrs(editor, block);
24450
      emptyBlock(caretNode);
24451
      return block;
24452
    };
24453
 
24454
    const getDetailsRoot = (editor, element) => editor.dom.getParent(element, isDetails);
24455
    const isAtDetailsEdge = (root, element, isTextBlock) => {
24456
      let node = element;
24457
      while (node && node !== root && isNull(node.nextSibling)) {
24458
        const parent = node.parentElement;
24459
        if (!parent || !isTextBlock(parent)) {
24460
          return isDetails(parent);
24461
        }
24462
        node = parent;
24463
      }
24464
      return false;
24465
    };
24466
    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()));
24467
    const insertNewLine = (editor, createNewBlock, parentBlock) => {
24468
      var _a, _b, _c;
24469
      const newBlock = createNewBlock(getForcedRootBlock(editor));
24470
      const root = getDetailsRoot(editor, parentBlock);
24471
      if (!root) {
24472
        return;
24473
      }
24474
      editor.dom.insertAfter(newBlock, root);
24475
      moveToCaretPosition(editor, newBlock);
24476
      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) {
24477
        editor.dom.remove(parentBlock);
24478
      }
24479
    };
24480
 
24481
    const hasFirstChild = (elm, name) => {
24482
      return elm.firstChild && elm.firstChild.nodeName === name;
24483
    };
24484
    const isFirstChild = elm => {
24485
      var _a;
24486
      return ((_a = elm.parentNode) === null || _a === void 0 ? void 0 : _a.firstChild) === elm;
24487
    };
24488
    const hasParent = (elm, parentName) => {
24489
      const parentNode = elm === null || elm === void 0 ? void 0 : elm.parentNode;
24490
      return isNonNullable(parentNode) && parentNode.nodeName === parentName;
24491
    };
24492
    const isListBlock = elm => {
24493
      return isNonNullable(elm) && /^(OL|UL|LI)$/.test(elm.nodeName);
24494
    };
24495
    const isListItem = elm => {
24496
      return isNonNullable(elm) && /^(LI|DT|DD)$/.test(elm.nodeName);
24497
    };
24498
    const isNestedList = elm => {
24499
      return isListBlock(elm) && isListBlock(elm.parentNode);
24500
    };
24501
    const getContainerBlock = containerBlock => {
24502
      const containerBlockParent = containerBlock.parentNode;
24503
      return isListItem(containerBlockParent) ? containerBlockParent : containerBlock;
24504
    };
24505
    const isFirstOrLastLi = (containerBlock, parentBlock, first) => {
24506
      let node = containerBlock[first ? 'firstChild' : 'lastChild'];
24507
      while (node) {
24508
        if (isElement$6(node)) {
24509
          break;
24510
        }
24511
        node = node[first ? 'nextSibling' : 'previousSibling'];
24512
      }
24513
      return node === parentBlock;
24514
    };
24515
    const getStyles = elm => foldl(mapToArray(getAllRaw(SugarElement.fromDom(elm)), (style, styleName) => `${ styleName }: ${ style };`), (acc, s) => acc + s, '');
24516
    const insert$4 = (editor, createNewBlock, containerBlock, parentBlock, newBlockName) => {
24517
      const dom = editor.dom;
24518
      const rng = editor.selection.getRng();
24519
      const containerParent = containerBlock.parentNode;
24520
      if (containerBlock === editor.getBody() || !containerParent) {
24521
        return;
24522
      }
24523
      if (isNestedList(containerBlock)) {
24524
        newBlockName = 'LI';
24525
      }
24526
      const parentBlockStyles = isListItem(parentBlock) ? getStyles(parentBlock) : undefined;
24527
      let newBlock = isListItem(parentBlock) && parentBlockStyles ? createNewBlock(newBlockName, { style: getStyles(parentBlock) }) : createNewBlock(newBlockName);
24528
      if (isFirstOrLastLi(containerBlock, parentBlock, true) && isFirstOrLastLi(containerBlock, parentBlock, false)) {
24529
        if (hasParent(containerBlock, 'LI')) {
24530
          const containerBlockParent = getContainerBlock(containerBlock);
24531
          dom.insertAfter(newBlock, containerBlockParent);
24532
          if (isFirstChild(containerBlock)) {
24533
            dom.remove(containerBlockParent);
24534
          } else {
24535
            dom.remove(containerBlock);
24536
          }
24537
        } else {
24538
          dom.replace(newBlock, containerBlock);
24539
        }
24540
      } else if (isFirstOrLastLi(containerBlock, parentBlock, true)) {
24541
        if (hasParent(containerBlock, 'LI')) {
24542
          dom.insertAfter(newBlock, getContainerBlock(containerBlock));
24543
          newBlock.appendChild(dom.doc.createTextNode(' '));
24544
          newBlock.appendChild(containerBlock);
24545
        } else {
24546
          containerParent.insertBefore(newBlock, containerBlock);
24547
        }
24548
        dom.remove(parentBlock);
24549
      } else if (isFirstOrLastLi(containerBlock, parentBlock, false)) {
24550
        dom.insertAfter(newBlock, getContainerBlock(containerBlock));
24551
        dom.remove(parentBlock);
24552
      } else {
24553
        containerBlock = getContainerBlock(containerBlock);
24554
        const tmpRng = rng.cloneRange();
24555
        tmpRng.setStartAfter(parentBlock);
24556
        tmpRng.setEndAfter(containerBlock);
24557
        const fragment = tmpRng.extractContents();
24558
        if (newBlockName === 'LI' && hasFirstChild(fragment, 'LI')) {
24559
          const previousChildren = filter$5(map$3(newBlock.children, SugarElement.fromDom), not(isTag('br')));
24560
          newBlock = fragment.firstChild;
24561
          dom.insertAfter(fragment, containerBlock);
24562
          each$e(previousChildren, child => prepend(SugarElement.fromDom(newBlock), child));
24563
          if (parentBlockStyles) {
24564
            newBlock.setAttribute('style', parentBlockStyles);
24565
          }
24566
        } else {
24567
          dom.insertAfter(fragment, containerBlock);
24568
          dom.insertAfter(newBlock, containerBlock);
24569
        }
24570
        dom.remove(parentBlock);
24571
      }
24572
      moveToCaretPosition(editor, newBlock);
24573
    };
24574
 
24575
    const trimZwsp = fragment => {
24576
      each$e(descendants$1(SugarElement.fromDom(fragment), isText$b), text => {
24577
        const rawNode = text.dom;
24578
        rawNode.nodeValue = trim$2(rawNode.data);
24579
      });
24580
    };
24581
    const isWithinNonEditableList = (editor, node) => {
24582
      const parentList = editor.dom.getParent(node, 'ol,ul,dl');
24583
      return parentList !== null && editor.dom.getContentEditableParent(parentList) === 'false';
24584
    };
24585
    const isEmptyAnchor = (dom, elm) => {
24586
      return elm && elm.nodeName === 'A' && dom.isEmpty(elm);
24587
    };
24588
    const containerAndSiblingName = (container, nodeName) => {
24589
      return container.nodeName === nodeName || container.previousSibling && container.previousSibling.nodeName === nodeName;
24590
    };
24591
    const canSplitBlock = (dom, node) => {
24592
      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';
24593
    };
24594
    const trimInlineElementsOnLeftSideOfBlock = (dom, nonEmptyElementsMap, block) => {
24595
      var _a;
24596
      const firstChilds = [];
24597
      if (!block) {
24598
        return;
24599
      }
24600
      let currentNode = block;
24601
      while (currentNode = currentNode.firstChild) {
24602
        if (dom.isBlock(currentNode)) {
24603
          return;
24604
        }
24605
        if (isElement$6(currentNode) && !nonEmptyElementsMap[currentNode.nodeName.toLowerCase()]) {
24606
          firstChilds.push(currentNode);
24607
        }
24608
      }
24609
      let i = firstChilds.length;
24610
      while (i--) {
24611
        currentNode = firstChilds[i];
24612
        if (!currentNode.hasChildNodes() || currentNode.firstChild === currentNode.lastChild && ((_a = currentNode.firstChild) === null || _a === void 0 ? void 0 : _a.nodeValue) === '') {
24613
          dom.remove(currentNode);
24614
        } else {
24615
          if (isEmptyAnchor(dom, currentNode)) {
24616
            dom.remove(currentNode);
24617
          }
24618
        }
24619
      }
24620
    };
24621
    const normalizeZwspOffset = (start, container, offset) => {
24622
      if (!isText$a(container)) {
24623
        return offset;
24624
      } else if (start) {
24625
        return offset === 1 && container.data.charAt(offset - 1) === ZWSP$1 ? 0 : offset;
24626
      } else {
24627
        return offset === container.data.length - 1 && container.data.charAt(offset) === ZWSP$1 ? container.data.length : offset;
24628
      }
24629
    };
24630
    const includeZwspInRange = rng => {
24631
      const newRng = rng.cloneRange();
24632
      newRng.setStart(rng.startContainer, normalizeZwspOffset(true, rng.startContainer, rng.startOffset));
24633
      newRng.setEnd(rng.endContainer, normalizeZwspOffset(false, rng.endContainer, rng.endOffset));
24634
      return newRng;
24635
    };
24636
    const trimLeadingLineBreaks = node => {
24637
      let currentNode = node;
24638
      do {
24639
        if (isText$a(currentNode)) {
24640
          currentNode.data = currentNode.data.replace(/^[\r\n]+/, '');
24641
        }
24642
        currentNode = currentNode.firstChild;
24643
      } while (currentNode);
24644
    };
24645
    const wrapSelfAndSiblingsInDefaultBlock = (editor, newBlockName, rng, container, offset) => {
24646
      var _a, _b;
24647
      const dom = editor.dom;
24648
      const editableRoot = (_a = getEditableRoot(dom, container)) !== null && _a !== void 0 ? _a : dom.getRoot();
24649
      let parentBlock = dom.getParent(container, dom.isBlock);
24650
      if (!parentBlock || !canSplitBlock(dom, parentBlock)) {
24651
        parentBlock = parentBlock || editableRoot;
24652
        if (!parentBlock.hasChildNodes()) {
24653
          const newBlock = dom.create(newBlockName);
24654
          setForcedBlockAttrs(editor, newBlock);
24655
          parentBlock.appendChild(newBlock);
24656
          rng.setStart(newBlock, 0);
24657
          rng.setEnd(newBlock, 0);
24658
          return newBlock;
24659
        }
24660
        let node = container;
24661
        while (node && node.parentNode !== parentBlock) {
24662
          node = node.parentNode;
24663
        }
24664
        let startNode;
24665
        while (node && !dom.isBlock(node)) {
24666
          startNode = node;
24667
          node = node.previousSibling;
24668
        }
24669
        const startNodeName = (_b = startNode === null || startNode === void 0 ? void 0 : startNode.parentElement) === null || _b === void 0 ? void 0 : _b.nodeName;
24670
        if (startNode && startNodeName && editor.schema.isValidChild(startNodeName, newBlockName.toLowerCase())) {
24671
          const startNodeParent = startNode.parentNode;
24672
          const newBlock = dom.create(newBlockName);
24673
          setForcedBlockAttrs(editor, newBlock);
24674
          startNodeParent.insertBefore(newBlock, startNode);
24675
          node = startNode;
24676
          while (node && !dom.isBlock(node)) {
24677
            const next = node.nextSibling;
24678
            newBlock.appendChild(node);
24679
            node = next;
24680
          }
24681
          rng.setStart(container, offset);
24682
          rng.setEnd(container, offset);
24683
        }
24684
      }
24685
      return container;
24686
    };
24687
    const addBrToBlockIfNeeded = (dom, block) => {
24688
      block.normalize();
24689
      const lastChild = block.lastChild;
24690
      if (!lastChild || isElement$6(lastChild) && /^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true))) {
24691
        dom.add(block, 'br');
24692
      }
24693
    };
24694
    const shouldEndContainer = (editor, container) => {
24695
      const optionValue = shouldEndContainerOnEmptyBlock(editor);
24696
      if (isNullable(container)) {
24697
        return false;
24698
      } else if (isString(optionValue)) {
24699
        return contains$2(Tools.explode(optionValue), container.nodeName.toLowerCase());
24700
      } else {
24701
        return optionValue;
24702
      }
24703
    };
24704
    const insert$3 = (editor, evt) => {
24705
      let container;
24706
      let offset;
24707
      let parentBlockName;
24708
      let containerBlock;
24709
      let isAfterLastNodeInContainer = false;
24710
      const dom = editor.dom;
24711
      const schema = editor.schema, nonEmptyElementsMap = schema.getNonEmptyElements();
24712
      const rng = editor.selection.getRng();
24713
      const newBlockName = getForcedRootBlock(editor);
24714
      const start = SugarElement.fromDom(rng.startContainer);
24715
      const child = child$1(start, rng.startOffset);
24716
      const isCef = child.exists(element => isHTMLElement$1(element) && !isEditable$2(element));
24717
      const collapsedAndCef = rng.collapsed && isCef;
24718
      const createNewBlock$1 = (name, styles) => {
24719
        return createNewBlock(editor, container, parentBlock, editableRoot, shouldKeepStyles(editor), name, styles);
24720
      };
24721
      const isCaretAtStartOrEndOfBlock = start => {
24722
        const normalizedOffset = normalizeZwspOffset(start, container, offset);
24723
        if (isText$a(container) && (start ? normalizedOffset > 0 : normalizedOffset < container.data.length)) {
24724
          return false;
24725
        }
24726
        if (container.parentNode === parentBlock && isAfterLastNodeInContainer && !start) {
24727
          return true;
24728
        }
24729
        if (start && isElement$6(container) && container === parentBlock.firstChild) {
24730
          return true;
24731
        }
24732
        if (containerAndSiblingName(container, 'TABLE') || containerAndSiblingName(container, 'HR')) {
24733
          return isAfterLastNodeInContainer && !start || !isAfterLastNodeInContainer && start;
24734
        }
24735
        const walker = new DomTreeWalker(container, parentBlock);
24736
        if (isText$a(container)) {
24737
          if (start && normalizedOffset === 0) {
24738
            walker.prev();
24739
          } else if (!start && normalizedOffset === container.data.length) {
24740
            walker.next();
24741
          }
24742
        }
24743
        let node;
24744
        while (node = walker.current()) {
24745
          if (isElement$6(node)) {
24746
            if (!node.getAttribute('data-mce-bogus')) {
24747
              const name = node.nodeName.toLowerCase();
24748
              if (nonEmptyElementsMap[name] && name !== 'br') {
24749
                return false;
24750
              }
24751
            }
24752
          } else if (isText$a(node) && !isWhitespaceText(node.data)) {
24753
            return false;
24754
          }
24755
          if (start) {
24756
            walker.prev();
24757
          } else {
24758
            walker.next();
24759
          }
24760
        }
24761
        return true;
24762
      };
24763
      const insertNewBlockAfter = () => {
24764
        let block;
24765
        if (/^(H[1-6]|PRE|FIGURE)$/.test(parentBlockName) && containerBlockName !== 'HGROUP') {
24766
          block = createNewBlock$1(newBlockName);
24767
        } else {
24768
          block = createNewBlock$1();
24769
        }
24770
        if (shouldEndContainer(editor, containerBlock) && canSplitBlock(dom, containerBlock) && dom.isEmpty(parentBlock, undefined, { includeZwsp: true })) {
24771
          block = dom.split(containerBlock, parentBlock);
24772
        } else {
24773
          dom.insertAfter(block, parentBlock);
24774
        }
24775
        moveToCaretPosition(editor, block);
24776
        return block;
24777
      };
24778
      normalize$2(dom, rng).each(normRng => {
24779
        rng.setStart(normRng.startContainer, normRng.startOffset);
24780
        rng.setEnd(normRng.endContainer, normRng.endOffset);
24781
      });
24782
      container = rng.startContainer;
24783
      offset = rng.startOffset;
24784
      const shiftKey = !!(evt && evt.shiftKey);
24785
      const ctrlKey = !!(evt && evt.ctrlKey);
24786
      if (isElement$6(container) && container.hasChildNodes() && !collapsedAndCef) {
24787
        isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
24788
        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
24789
        if (isAfterLastNodeInContainer && isText$a(container)) {
24790
          offset = container.data.length;
24791
        } else {
24792
          offset = 0;
24793
        }
24794
      }
24795
      const editableRoot = getEditableRoot(dom, container);
24796
      if (!editableRoot || isWithinNonEditableList(editor, container)) {
24797
        return;
24798
      }
24799
      if (!shiftKey) {
24800
        container = wrapSelfAndSiblingsInDefaultBlock(editor, newBlockName, rng, container, offset);
24801
      }
24802
      let parentBlock = dom.getParent(container, dom.isBlock) || dom.getRoot();
24803
      containerBlock = isNonNullable(parentBlock === null || parentBlock === void 0 ? void 0 : parentBlock.parentNode) ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
24804
      parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : '';
24805
      const containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
24806
      if (containerBlockName === 'LI' && !ctrlKey) {
24807
        const liBlock = containerBlock;
24808
        parentBlock = liBlock;
24809
        containerBlock = liBlock.parentNode;
24810
        parentBlockName = containerBlockName;
24811
      }
24812
      if (isElement$6(containerBlock) && isLastEmptyBlockInDetails(editor, shiftKey, parentBlock)) {
24813
        return insertNewLine(editor, createNewBlock$1, parentBlock);
24814
      }
24815
      if (/^(LI|DT|DD)$/.test(parentBlockName) && isElement$6(containerBlock)) {
24816
        if (dom.isEmpty(parentBlock)) {
24817
          insert$4(editor, createNewBlock$1, containerBlock, parentBlock, newBlockName);
24818
          return;
24819
        }
24820
      }
24821
      if (!collapsedAndCef && (parentBlock === editor.getBody() || !canSplitBlock(dom, parentBlock))) {
24822
        return;
24823
      }
24824
      const parentBlockParent = parentBlock.parentNode;
24825
      let newBlock;
24826
      if (collapsedAndCef) {
24827
        newBlock = createNewBlock$1(newBlockName);
24828
        child.fold(() => {
24829
          append$1(start, SugarElement.fromDom(newBlock));
24830
        }, child => {
24831
          before$3(child, SugarElement.fromDom(newBlock));
24832
        });
24833
        editor.selection.setCursorLocation(newBlock, 0);
24834
      } else if (isCaretContainerBlock$1(parentBlock)) {
24835
        newBlock = showCaretContainerBlock(parentBlock);
24836
        if (dom.isEmpty(parentBlock)) {
24837
          emptyBlock(parentBlock);
24838
        }
24839
        setForcedBlockAttrs(editor, newBlock);
24840
        moveToCaretPosition(editor, newBlock);
24841
      } else if (isCaretAtStartOrEndOfBlock(false)) {
24842
        newBlock = insertNewBlockAfter();
24843
      } else if (isCaretAtStartOrEndOfBlock(true) && parentBlockParent) {
24844
        newBlock = parentBlockParent.insertBefore(createNewBlock$1(), parentBlock);
24845
        const isNearChildren = hasChildNodes(SugarElement.fromDom(rng.startContainer)) && rng.collapsed;
24846
        moveToCaretPosition(editor, containerAndSiblingName(parentBlock, 'HR') || isNearChildren ? newBlock : parentBlock);
24847
      } else {
24848
        const tmpRng = includeZwspInRange(rng).cloneRange();
24849
        tmpRng.setEndAfter(parentBlock);
24850
        const fragment = tmpRng.extractContents();
24851
        trimZwsp(fragment);
24852
        trimLeadingLineBreaks(fragment);
24853
        newBlock = fragment.firstChild;
24854
        dom.insertAfter(fragment, parentBlock);
24855
        trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock);
24856
        addBrToBlockIfNeeded(dom, parentBlock);
24857
        if (dom.isEmpty(parentBlock)) {
24858
          emptyBlock(parentBlock);
24859
        }
24860
        newBlock.normalize();
24861
        if (dom.isEmpty(newBlock)) {
24862
          dom.remove(newBlock);
24863
          insertNewBlockAfter();
24864
        } else {
24865
          setForcedBlockAttrs(editor, newBlock);
24866
          moveToCaretPosition(editor, newBlock);
24867
        }
24868
      }
24869
      dom.setAttrib(newBlock, 'id', '');
24870
      editor.dispatch('NewBlock', { newBlock });
24871
    };
24872
    const fakeEventName$1 = 'insertParagraph';
24873
    const blockbreak = {
24874
      insert: insert$3,
24875
      fakeEventName: fakeEventName$1
24876
    };
24877
 
24878
    const hasRightSideContent = (schema, container, parentBlock) => {
24879
      const walker = new DomTreeWalker(container, parentBlock);
24880
      let node;
24881
      const nonEmptyElementsMap = schema.getNonEmptyElements();
24882
      while (node = walker.next()) {
24883
        if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || isText$a(node) && node.length > 0) {
24884
          return true;
24885
        }
24886
      }
24887
      return false;
24888
    };
24889
    const moveSelectionToBr = (editor, brElm, extraBr) => {
24890
      const rng = editor.dom.createRng();
24891
      if (!extraBr) {
24892
        rng.setStartAfter(brElm);
24893
        rng.setEndAfter(brElm);
24894
      } else {
24895
        rng.setStartBefore(brElm);
24896
        rng.setEndBefore(brElm);
24897
      }
24898
      editor.selection.setRng(rng);
24899
      scrollRangeIntoView(editor, rng);
24900
    };
24901
    const insertBrAtCaret = (editor, evt) => {
24902
      const selection = editor.selection;
24903
      const dom = editor.dom;
24904
      const rng = selection.getRng();
24905
      let brElm;
24906
      let extraBr = false;
24907
      normalize$2(dom, rng).each(normRng => {
24908
        rng.setStart(normRng.startContainer, normRng.startOffset);
24909
        rng.setEnd(normRng.endContainer, normRng.endOffset);
24910
      });
24911
      let offset = rng.startOffset;
24912
      let container = rng.startContainer;
24913
      if (isElement$6(container) && container.hasChildNodes()) {
24914
        const isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
24915
        container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
24916
        if (isAfterLastNodeInContainer && isText$a(container)) {
24917
          offset = container.data.length;
24918
        } else {
24919
          offset = 0;
24920
        }
24921
      }
24922
      let parentBlock = dom.getParent(container, dom.isBlock);
24923
      const containerBlock = parentBlock && parentBlock.parentNode ? dom.getParent(parentBlock.parentNode, dom.isBlock) : null;
24924
      const containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : '';
24925
      const isControlKey = !!(evt && evt.ctrlKey);
24926
      if (containerBlockName === 'LI' && !isControlKey) {
24927
        parentBlock = containerBlock;
24928
      }
24929
      if (isText$a(container) && offset >= container.data.length) {
24930
        if (!hasRightSideContent(editor.schema, container, parentBlock || dom.getRoot())) {
24931
          brElm = dom.create('br');
24932
          rng.insertNode(brElm);
24933
          rng.setStartAfter(brElm);
24934
          rng.setEndAfter(brElm);
24935
          extraBr = true;
24936
        }
24937
      }
24938
      brElm = dom.create('br');
24939
      rangeInsertNode(dom, rng, brElm);
24940
      moveSelectionToBr(editor, brElm, extraBr);
24941
      editor.undoManager.add();
24942
    };
24943
    const insertBrBefore = (editor, inline) => {
24944
      const br = SugarElement.fromTag('br');
24945
      before$3(SugarElement.fromDom(inline), br);
24946
      editor.undoManager.add();
24947
    };
24948
    const insertBrAfter = (editor, inline) => {
24949
      if (!hasBrAfter(editor.getBody(), inline)) {
24950
        after$4(SugarElement.fromDom(inline), SugarElement.fromTag('br'));
24951
      }
24952
      const br = SugarElement.fromTag('br');
24953
      after$4(SugarElement.fromDom(inline), br);
24954
      moveSelectionToBr(editor, br.dom, false);
24955
      editor.undoManager.add();
24956
    };
24957
    const isBeforeBr = pos => {
24958
      return isBr$6(pos.getNode());
24959
    };
24960
    const hasBrAfter = (rootNode, startNode) => {
24961
      if (isBeforeBr(CaretPosition.after(startNode))) {
24962
        return true;
24963
      } else {
24964
        return nextPosition(rootNode, CaretPosition.after(startNode)).map(pos => {
24965
          return isBr$6(pos.getNode());
24966
        }).getOr(false);
24967
      }
24968
    };
24969
    const isAnchorLink = elm => {
24970
      return elm && elm.nodeName === 'A' && 'href' in elm;
24971
    };
24972
    const isInsideAnchor = location => {
24973
      return location.fold(never, isAnchorLink, isAnchorLink, never);
24974
    };
24975
    const readInlineAnchorLocation = editor => {
24976
      const isInlineTarget$1 = curry(isInlineTarget, editor);
24977
      const position = CaretPosition.fromRangeStart(editor.selection.getRng());
24978
      return readLocation(isInlineTarget$1, editor.getBody(), position).filter(isInsideAnchor);
24979
    };
24980
    const insertBrOutsideAnchor = (editor, location) => {
24981
      location.fold(noop, curry(insertBrBefore, editor), curry(insertBrAfter, editor), noop);
24982
    };
24983
    const insert$2 = (editor, evt) => {
24984
      const anchorLocation = readInlineAnchorLocation(editor);
24985
      if (anchorLocation.isSome()) {
24986
        anchorLocation.each(curry(insertBrOutsideAnchor, editor));
24987
      } else {
24988
        insertBrAtCaret(editor, evt);
24989
      }
24990
    };
24991
    const fakeEventName = 'insertLineBreak';
24992
    const linebreak = {
24993
      insert: insert$2,
24994
      fakeEventName
24995
    };
24996
 
24997
    const matchesSelector = (editor, selector) => {
24998
      return getParentBlock$1(editor).filter(parentBlock => {
24999
        return selector.length > 0 && is$1(SugarElement.fromDom(parentBlock), selector);
25000
      }).isSome();
25001
    };
25002
    const shouldInsertBr = editor => {
25003
      return matchesSelector(editor, getBrNewLineSelector(editor));
25004
    };
25005
    const shouldBlockNewLine$1 = editor => {
25006
      return matchesSelector(editor, getNoNewLineSelector(editor));
25007
    };
25008
 
25009
    const newLineAction = Adt.generate([
25010
      { br: [] },
25011
      { block: [] },
25012
      { none: [] }
25013
    ]);
25014
    const shouldBlockNewLine = (editor, _shiftKey) => {
25015
      return shouldBlockNewLine$1(editor);
25016
    };
25017
    const inListBlock = requiredState => {
25018
      return (editor, _shiftKey) => {
25019
        return isListItemParentBlock(editor) === requiredState;
25020
      };
25021
    };
25022
    const inBlock = (blockName, requiredState) => (editor, _shiftKey) => {
25023
      const state = getParentBlockName(editor) === blockName.toUpperCase();
25024
      return state === requiredState;
25025
    };
25026
    const inCefBlock = editor => {
25027
      const editableRoot = getEditableRoot(editor.dom, editor.selection.getStart());
25028
      return isNullable(editableRoot);
25029
    };
25030
    const inPreBlock = requiredState => inBlock('pre', requiredState);
25031
    const inSummaryBlock = () => inBlock('summary', true);
25032
    const shouldPutBrInPre = requiredState => {
25033
      return (editor, _shiftKey) => {
25034
        return shouldPutBrInPre$1(editor) === requiredState;
25035
      };
25036
    };
25037
    const inBrContext = (editor, _shiftKey) => {
25038
      return shouldInsertBr(editor);
25039
    };
25040
    const hasShiftKey = (_editor, shiftKey) => {
25041
      return shiftKey;
25042
    };
25043
    const canInsertIntoEditableRoot = editor => {
25044
      const forcedRootBlock = getForcedRootBlock(editor);
25045
      const rootEditable = getEditableRoot(editor.dom, editor.selection.getStart());
25046
      return isNonNullable(rootEditable) && editor.schema.isValidChild(rootEditable.nodeName, forcedRootBlock);
25047
    };
25048
    const isInRootWithEmptyOrCEF = editor => {
25049
      const rng = editor.selection.getRng();
25050
      const start = SugarElement.fromDom(rng.startContainer);
25051
      const child = child$1(start, rng.startOffset);
25052
      const isCefOpt = child.map(element => isHTMLElement$1(element) && !isEditable$2(element));
25053
      return rng.collapsed && isCefOpt.getOr(true);
25054
    };
25055
    const match = (predicates, action) => {
25056
      return (editor, shiftKey) => {
25057
        const isMatch = foldl(predicates, (res, p) => {
25058
          return res && p(editor, shiftKey);
25059
        }, true);
25060
        return isMatch ? Optional.some(action) : Optional.none();
25061
      };
25062
    };
25063
    const getAction = (editor, evt) => {
25064
      return evaluateUntil([
25065
        match([shouldBlockNewLine], newLineAction.none()),
25066
        match([
25067
          inPreBlock(true),
25068
          inCefBlock
25069
        ], newLineAction.none()),
25070
        match([inSummaryBlock()], newLineAction.br()),
25071
        match([
25072
          inPreBlock(true),
25073
          shouldPutBrInPre(false),
25074
          hasShiftKey
25075
        ], newLineAction.br()),
25076
        match([
25077
          inPreBlock(true),
25078
          shouldPutBrInPre(false)
25079
        ], newLineAction.block()),
25080
        match([
25081
          inPreBlock(true),
25082
          shouldPutBrInPre(true),
25083
          hasShiftKey
25084
        ], newLineAction.block()),
25085
        match([
25086
          inPreBlock(true),
25087
          shouldPutBrInPre(true)
25088
        ], newLineAction.br()),
25089
        match([
25090
          inListBlock(true),
25091
          hasShiftKey
25092
        ], newLineAction.br()),
25093
        match([inListBlock(true)], newLineAction.block()),
25094
        match([inBrContext], newLineAction.br()),
25095
        match([hasShiftKey], newLineAction.br()),
25096
        match([canInsertIntoEditableRoot], newLineAction.block()),
25097
        match([isInRootWithEmptyOrCEF], newLineAction.block())
25098
      ], [
25099
        editor,
25100
        !!(evt && evt.shiftKey)
25101
      ]).getOr(newLineAction.none());
25102
    };
25103
 
25104
    const insertBreak = (breakType, editor, evt) => {
25105
      if (!editor.selection.isCollapsed()) {
25106
        execEditorDeleteCommand(editor);
25107
      }
25108
      if (isNonNullable(evt)) {
25109
        const event = fireBeforeInputEvent(editor, breakType.fakeEventName);
25110
        if (event.isDefaultPrevented()) {
25111
          return;
25112
        }
25113
      }
25114
      breakType.insert(editor, evt);
25115
      if (isNonNullable(evt)) {
25116
        fireInputEvent(editor, breakType.fakeEventName);
25117
      }
25118
    };
25119
    const insert$1 = (editor, evt) => {
25120
      const br = () => insertBreak(linebreak, editor, evt);
25121
      const block = () => insertBreak(blockbreak, editor, evt);
25122
      const logicalAction = getAction(editor, evt);
25123
      switch (getNewlineBehavior(editor)) {
25124
      case 'linebreak':
25125
        logicalAction.fold(br, br, noop);
25126
        break;
25127
      case 'block':
25128
        logicalAction.fold(block, block, noop);
25129
        break;
25130
      case 'invert':
25131
        logicalAction.fold(block, br, noop);
25132
        break;
25133
      default:
25134
        logicalAction.fold(br, block, noop);
25135
        break;
25136
      }
25137
    };
25138
 
25139
    const platform$1 = detect$2();
25140
    const isIOSSafari = platform$1.os.isiOS() && platform$1.browser.isSafari();
25141
    const handleEnterKeyEvent = (editor, event) => {
25142
      if (event.isDefaultPrevented()) {
25143
        return;
25144
      }
25145
      event.preventDefault();
25146
      endTypingLevelIgnoreLocks(editor.undoManager);
25147
      editor.undoManager.transact(() => {
25148
        insert$1(editor, event);
25149
      });
25150
    };
25151
    const isCaretAfterKoreanCharacter = rng => {
25152
      if (!rng.collapsed) {
25153
        return false;
25154
      }
25155
      const startContainer = rng.startContainer;
25156
      if (isText$a(startContainer)) {
25157
        const koreanCharRegex = /^[\uAC00-\uD7AF\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uD7B0-\uD7FF]$/;
25158
        const char = startContainer.data.charAt(rng.startOffset - 1);
25159
        return koreanCharRegex.test(char);
25160
      } else {
25161
        return false;
25162
      }
25163
    };
25164
    const setup$i = editor => {
25165
      let iOSSafariKeydownBookmark = Optional.none();
25166
      const iOSSafariKeydownOverride = editor => {
25167
        iOSSafariKeydownBookmark = Optional.some(editor.selection.getBookmark());
25168
        editor.undoManager.add();
25169
      };
25170
      const iOSSafariKeyupOverride = (editor, event) => {
25171
        editor.undoManager.undo();
25172
        iOSSafariKeydownBookmark.fold(noop, b => editor.selection.moveToBookmark(b));
25173
        handleEnterKeyEvent(editor, event);
25174
        iOSSafariKeydownBookmark = Optional.none();
25175
      };
25176
      editor.on('keydown', event => {
25177
        if (event.keyCode === VK.ENTER) {
25178
          if (isIOSSafari && isCaretAfterKoreanCharacter(editor.selection.getRng())) {
25179
            iOSSafariKeydownOverride(editor);
25180
          } else {
25181
            handleEnterKeyEvent(editor, event);
25182
          }
25183
        }
25184
      });
25185
      editor.on('keyup', event => {
25186
        if (event.keyCode === VK.ENTER) {
25187
          iOSSafariKeydownBookmark.each(() => iOSSafariKeyupOverride(editor, event));
25188
        }
25189
      });
25190
    };
25191
 
25192
    const executeKeydownOverride$2 = (editor, caret, evt) => {
25193
      const isMac = Env.os.isMacOS() || Env.os.isiOS();
25194
      execute([
25195
        {
25196
          keyCode: VK.END,
25197
          action: action(moveToLineEndPoint$1, editor, true)
25198
        },
25199
        {
25200
          keyCode: VK.HOME,
25201
          action: action(moveToLineEndPoint$1, editor, false)
25202
        },
25203
        ...!isMac ? [
25204
          {
25205
            keyCode: VK.HOME,
25206
            action: action(selectToEndPoint, editor, false),
25207
            ctrlKey: true,
25208
            shiftKey: true
25209
          },
25210
          {
25211
            keyCode: VK.END,
25212
            action: action(selectToEndPoint, editor, true),
25213
            ctrlKey: true,
25214
            shiftKey: true
25215
          }
25216
        ] : [],
25217
        {
25218
          keyCode: VK.END,
25219
          action: action(moveToLineEndPoint, editor, true)
25220
        },
25221
        {
25222
          keyCode: VK.HOME,
25223
          action: action(moveToLineEndPoint, editor, false)
25224
        },
25225
        {
25226
          keyCode: VK.END,
25227
          action: action(moveToLineEndPoint$2, editor, true, caret)
25228
        },
25229
        {
25230
          keyCode: VK.HOME,
25231
          action: action(moveToLineEndPoint$2, editor, false, caret)
25232
        }
25233
      ], evt).each(_ => {
25234
        evt.preventDefault();
25235
      });
25236
    };
25237
    const setup$h = (editor, caret) => {
25238
      editor.on('keydown', evt => {
25239
        if (!evt.isDefaultPrevented()) {
25240
          executeKeydownOverride$2(editor, caret, evt);
25241
        }
25242
      });
25243
    };
25244
 
25245
    const setup$g = editor => {
25246
      editor.on('input', e => {
25247
        if (!e.isComposing) {
25248
          normalizeNbspsInEditor(editor);
25249
        }
25250
      });
25251
    };
25252
 
25253
    const platform = detect$2();
25254
    const executeKeyupAction = (editor, caret, evt) => {
25255
      execute([
25256
        {
25257
          keyCode: VK.PAGE_UP,
25258
          action: action(moveToLineEndPoint$2, editor, false, caret)
25259
        },
25260
        {
25261
          keyCode: VK.PAGE_DOWN,
25262
          action: action(moveToLineEndPoint$2, editor, true, caret)
25263
        }
25264
      ], evt);
25265
    };
25266
    const stopImmediatePropagation = e => e.stopImmediatePropagation();
25267
    const isPageUpDown = evt => evt.keyCode === VK.PAGE_UP || evt.keyCode === VK.PAGE_DOWN;
25268
    const setNodeChangeBlocker = (blocked, editor, block) => {
25269
      if (block && !blocked.get()) {
25270
        editor.on('NodeChange', stopImmediatePropagation, true);
25271
      } else if (!block && blocked.get()) {
25272
        editor.off('NodeChange', stopImmediatePropagation);
25273
      }
25274
      blocked.set(block);
25275
    };
25276
    const setup$f = (editor, caret) => {
25277
      if (platform.os.isMacOS()) {
25278
        return;
25279
      }
25280
      const blocked = Cell(false);
25281
      editor.on('keydown', evt => {
25282
        if (isPageUpDown(evt)) {
25283
          setNodeChangeBlocker(blocked, editor, true);
25284
        }
25285
      });
25286
      editor.on('keyup', evt => {
25287
        if (!evt.isDefaultPrevented()) {
25288
          executeKeyupAction(editor, caret, evt);
25289
        }
25290
        if (isPageUpDown(evt) && blocked.get()) {
25291
          setNodeChangeBlocker(blocked, editor, false);
25292
          editor.nodeChanged();
25293
        }
25294
      });
25295
    };
25296
 
25297
    const setup$e = editor => {
25298
      editor.on('beforeinput', e => {
25299
        if (!editor.selection.isEditable() || exists(e.getTargetRanges(), rng => !isEditableRange(editor.dom, rng))) {
25300
          e.preventDefault();
25301
        }
25302
      });
25303
    };
25304
 
25305
    const insertTextAtPosition = (text, pos) => {
25306
      const container = pos.container();
25307
      const offset = pos.offset();
25308
      if (isText$a(container)) {
25309
        container.insertData(offset, text);
25310
        return Optional.some(CaretPosition(container, offset + text.length));
25311
      } else {
25312
        return getElementFromPosition(pos).map(elm => {
25313
          const textNode = SugarElement.fromText(text);
25314
          if (pos.isAtEnd()) {
25315
            after$4(elm, textNode);
25316
          } else {
25317
            before$3(elm, textNode);
25318
          }
25319
          return CaretPosition(textNode.dom, text.length);
25320
        });
25321
      }
25322
    };
25323
    const insertNbspAtPosition = curry(insertTextAtPosition, nbsp);
25324
    const insertSpaceAtPosition = curry(insertTextAtPosition, ' ');
25325
 
25326
    const insertSpaceOrNbspAtPosition = (root, pos, schema) => needsToHaveNbsp(root, pos, schema) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
25327
    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)));
25328
    const insertInlineBoundarySpaceOrNbsp = (root, pos, schema) => checkPos => needsToHaveNbsp(root, checkPos, schema) ? insertNbspAtPosition(pos) : insertSpaceAtPosition(pos);
25329
    const setSelection = editor => pos => {
25330
      editor.selection.setRng(pos.toRange());
25331
      editor.nodeChanged();
25332
    };
25333
    const isInsideSummary = (domUtils, node) => domUtils.isEditable(domUtils.getParent(node, 'summary'));
25334
    const insertSpaceOrNbspAtSelection = editor => {
25335
      const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
25336
      const root = SugarElement.fromDom(editor.getBody());
25337
      if (editor.selection.isCollapsed()) {
25338
        const isInlineTarget$1 = curry(isInlineTarget, editor);
25339
        const caretPosition = CaretPosition.fromRangeStart(editor.selection.getRng());
25340
        return readLocation(isInlineTarget$1, editor.getBody(), caretPosition).bind(locationToCaretPosition(root)).map(checkPos => () => insertInlineBoundarySpaceOrNbsp(root, pos, editor.schema)(checkPos).each(setSelection(editor)));
25341
      } else {
25342
        return Optional.none();
25343
      }
25344
    };
25345
    const insertSpaceInSummaryAtSelectionOnFirefox = editor => {
25346
      const insertSpaceThunk = () => {
25347
        const root = SugarElement.fromDom(editor.getBody());
25348
        if (!editor.selection.isCollapsed()) {
25349
          editor.getDoc().execCommand('Delete');
25350
        }
25351
        const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
25352
        insertSpaceOrNbspAtPosition(root, pos, editor.schema).each(setSelection(editor));
25353
      };
25354
      return someIf(Env.browser.isFirefox() && editor.selection.isEditable() && isInsideSummary(editor.dom, editor.selection.getRng().startContainer), insertSpaceThunk);
25355
    };
25356
 
25357
    const executeKeydownOverride$1 = (editor, evt) => {
25358
      executeWithDelayedAction([
25359
        {
25360
          keyCode: VK.SPACEBAR,
25361
          action: action(insertSpaceOrNbspAtSelection, editor)
25362
        },
25363
        {
25364
          keyCode: VK.SPACEBAR,
25365
          action: action(insertSpaceInSummaryAtSelectionOnFirefox, editor)
25366
        }
25367
      ], evt).each(applyAction => {
25368
        evt.preventDefault();
25369
        const event = fireBeforeInputEvent(editor, 'insertText', { data: ' ' });
25370
        if (!event.isDefaultPrevented()) {
25371
          applyAction();
25372
          fireInputEvent(editor, 'insertText', { data: ' ' });
25373
        }
25374
      });
25375
    };
25376
    const setup$d = editor => {
25377
      editor.on('keydown', evt => {
25378
        if (!evt.isDefaultPrevented()) {
25379
          executeKeydownOverride$1(editor, evt);
25380
        }
25381
      });
25382
    };
25383
 
25384
    const tableTabNavigation = editor => {
25385
      if (hasTableTabNavigation(editor)) {
25386
        return [
25387
          {
25388
            keyCode: VK.TAB,
25389
            action: action(handleTab, editor, true)
25390
          },
25391
          {
25392
            keyCode: VK.TAB,
25393
            shiftKey: true,
25394
            action: action(handleTab, editor, false)
25395
          }
25396
        ];
25397
      } else {
25398
        return [];
25399
      }
25400
    };
25401
    const executeKeydownOverride = (editor, evt) => {
25402
      execute([...tableTabNavigation(editor)], evt).each(_ => {
25403
        evt.preventDefault();
25404
      });
25405
    };
25406
    const setup$c = editor => {
25407
      editor.on('keydown', evt => {
25408
        if (!evt.isDefaultPrevented()) {
25409
          executeKeydownOverride(editor, evt);
25410
        }
25411
      });
25412
    };
25413
 
25414
    const setup$b = editor => {
25415
      editor.addShortcut('Meta+P', '', 'mcePrint');
25416
      setup$k(editor);
25417
      if (isRtc(editor)) {
25418
        return Cell(null);
25419
      } else {
25420
        const caret = setupSelectedState(editor);
25421
        setup$e(editor);
25422
        setup$m(editor);
25423
        setup$l(editor, caret);
25424
        setup$j(editor, caret);
25425
        setup$i(editor);
25426
        setup$d(editor);
25427
        setup$g(editor);
25428
        setup$c(editor);
25429
        setup$h(editor, caret);
25430
        setup$f(editor, caret);
25431
        return caret;
25432
      }
25433
    };
25434
 
25435
    class NodeChange {
25436
      constructor(editor) {
25437
        this.lastPath = [];
25438
        this.editor = editor;
25439
        let lastRng;
25440
        const self = this;
25441
        if (!('onselectionchange' in editor.getDoc())) {
25442
          editor.on('NodeChange click mouseup keyup focus', e => {
25443
            const nativeRng = editor.selection.getRng();
25444
            const fakeRng = {
25445
              startContainer: nativeRng.startContainer,
25446
              startOffset: nativeRng.startOffset,
25447
              endContainer: nativeRng.endContainer,
25448
              endOffset: nativeRng.endOffset
25449
            };
25450
            if (e.type === 'nodechange' || !isEq$4(fakeRng, lastRng)) {
25451
              editor.dispatch('SelectionChange');
25452
            }
25453
            lastRng = fakeRng;
25454
          });
25455
        }
25456
        editor.on('contextmenu', () => {
25457
          editor.dispatch('SelectionChange');
25458
        });
25459
        editor.on('SelectionChange', () => {
25460
          const startElm = editor.selection.getStart(true);
25461
          if (!startElm) {
25462
            return;
25463
          }
25464
          if (hasAnyRanges(editor) && !self.isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
25465
            editor.nodeChanged({ selectionChange: true });
25466
          }
25467
        });
25468
        editor.on('mouseup', e => {
25469
          if (!e.isDefaultPrevented() && hasAnyRanges(editor)) {
25470
            if (editor.selection.getNode().nodeName === 'IMG') {
25471
              Delay.setEditorTimeout(editor, () => {
25472
                editor.nodeChanged();
25473
              });
25474
            } else {
25475
              editor.nodeChanged();
25476
            }
25477
          }
25478
        });
25479
      }
25480
      nodeChanged(args = {}) {
25481
        const selection = this.editor.selection;
25482
        let node;
25483
        if (this.editor.initialized && selection && !shouldDisableNodeChange(this.editor) && !this.editor.mode.isReadOnly()) {
25484
          const root = this.editor.getBody();
25485
          node = selection.getStart(true) || root;
25486
          if (node.ownerDocument !== this.editor.getDoc() || !this.editor.dom.isChildOf(node, root)) {
25487
            node = root;
25488
          }
25489
          const parents = [];
25490
          this.editor.dom.getParent(node, node => {
25491
            if (node === root) {
25492
              return true;
25493
            } else {
25494
              parents.push(node);
25495
              return false;
25496
            }
25497
          });
25498
          this.editor.dispatch('NodeChange', {
25499
            ...args,
25500
            element: node,
25501
            parents
25502
          });
25503
        }
25504
      }
25505
      isSameElementPath(startElm) {
25506
        let i;
25507
        const editor = this.editor;
25508
        const currentPath = reverse(editor.dom.getParents(startElm, always, editor.getBody()));
25509
        if (currentPath.length === this.lastPath.length) {
25510
          for (i = currentPath.length; i >= 0; i--) {
25511
            if (currentPath[i] !== this.lastPath[i]) {
25512
              break;
25513
            }
25514
          }
25515
          if (i === -1) {
25516
            this.lastPath = currentPath;
25517
            return true;
25518
          }
25519
        }
25520
        this.lastPath = currentPath;
25521
        return false;
25522
      }
25523
    }
25524
 
25525
    const imageId = generate$1('image');
25526
    const getDragImage = transfer => {
25527
      const dt = transfer;
25528
      return Optional.from(dt[imageId]);
25529
    };
25530
    const setDragImage = (transfer, imageData) => {
25531
      const dt = transfer;
25532
      dt[imageId] = imageData;
25533
    };
25534
 
25535
    const eventId = generate$1('event');
25536
    const getEvent = transfer => {
25537
      const dt = transfer;
25538
      return Optional.from(dt[eventId]);
25539
    };
25540
    const mkSetEventFn = type => transfer => {
25541
      const dt = transfer;
25542
      dt[eventId] = type;
25543
    };
25544
    const setEvent = (transfer, type) => mkSetEventFn(type)(transfer);
25545
    const setDragstartEvent = mkSetEventFn(0);
25546
    const setDropEvent = mkSetEventFn(2);
25547
    const setDragendEvent = mkSetEventFn(1);
25548
    const checkEvent = expectedType => transfer => {
25549
      const dt = transfer;
25550
      return Optional.from(dt[eventId]).exists(type => type === expectedType);
25551
    };
25552
    const isInDragStartEvent = checkEvent(0);
25553
 
25554
    const createEmptyFileList = () => Object.freeze({
25555
      length: 0,
25556
      item: _ => null
25557
    });
25558
 
25559
    const modeId = generate$1('mode');
25560
    const getMode = transfer => {
25561
      const dt = transfer;
25562
      return Optional.from(dt[modeId]);
25563
    };
25564
    const mkSetModeFn = mode => transfer => {
25565
      const dt = transfer;
25566
      dt[modeId] = mode;
25567
    };
25568
    const setMode$1 = (transfer, mode) => mkSetModeFn(mode)(transfer);
25569
    const setReadWriteMode = mkSetModeFn(0);
25570
    const setReadOnlyMode = mkSetModeFn(2);
25571
    const setProtectedMode = mkSetModeFn(1);
25572
    const checkMode = expectedMode => transfer => {
25573
      const dt = transfer;
25574
      return Optional.from(dt[modeId]).exists(mode => mode === expectedMode);
25575
    };
25576
    const isInReadWriteMode = checkMode(0);
25577
    const isInProtectedMode = checkMode(1);
25578
 
25579
    const normalizeItems = (dataTransfer, itemsImpl) => ({
25580
      ...itemsImpl,
25581
      get length() {
25582
        return itemsImpl.length;
25583
      },
25584
      add: (data, type) => {
25585
        if (isInReadWriteMode(dataTransfer)) {
25586
          if (isString(data)) {
25587
            if (!isUndefined(type)) {
25588
              return itemsImpl.add(data, type);
25589
            }
25590
          } else {
25591
            return itemsImpl.add(data);
25592
          }
25593
        }
25594
        return null;
25595
      },
25596
      remove: idx => {
25597
        if (isInReadWriteMode(dataTransfer)) {
25598
          itemsImpl.remove(idx);
25599
        }
25600
      },
25601
      clear: () => {
25602
        if (isInReadWriteMode(dataTransfer)) {
25603
          itemsImpl.clear();
25604
        }
25605
      }
25606
    });
25607
 
25608
    const validDropEffects = [
25609
      'none',
25610
      'copy',
25611
      'link',
25612
      'move'
25613
    ];
25614
    const validEffectAlloweds = [
25615
      'none',
25616
      'copy',
25617
      'copyLink',
25618
      'copyMove',
25619
      'link',
25620
      'linkMove',
25621
      'move',
25622
      'all',
25623
      'uninitialized'
25624
    ];
25625
    const createDataTransfer = () => {
25626
      const dataTransferImpl = new window.DataTransfer();
25627
      let dropEffect = 'move';
25628
      let effectAllowed = 'all';
25629
      const dataTransfer = {
25630
        get dropEffect() {
25631
          return dropEffect;
25632
        },
25633
        set dropEffect(effect) {
25634
          if (contains$2(validDropEffects, effect)) {
25635
            dropEffect = effect;
25636
          }
25637
        },
25638
        get effectAllowed() {
25639
          return effectAllowed;
25640
        },
25641
        set effectAllowed(allowed) {
25642
          if (isInDragStartEvent(dataTransfer) && contains$2(validEffectAlloweds, allowed)) {
25643
            effectAllowed = allowed;
25644
          }
25645
        },
25646
        get items() {
25647
          return normalizeItems(dataTransfer, dataTransferImpl.items);
25648
        },
25649
        get files() {
25650
          if (isInProtectedMode(dataTransfer)) {
25651
            return createEmptyFileList();
25652
          } else {
25653
            return dataTransferImpl.files;
25654
          }
25655
        },
25656
        get types() {
25657
          return dataTransferImpl.types;
25658
        },
25659
        setDragImage: (image, x, y) => {
25660
          if (isInReadWriteMode(dataTransfer)) {
25661
            setDragImage(dataTransfer, {
25662
              image,
25663
              x,
25664
              y
25665
            });
25666
            dataTransferImpl.setDragImage(image, x, y);
25667
          }
25668
        },
25669
        getData: format => {
25670
          if (isInProtectedMode(dataTransfer)) {
25671
            return '';
25672
          } else {
25673
            return dataTransferImpl.getData(format);
25674
          }
25675
        },
25676
        setData: (format, data) => {
25677
          if (isInReadWriteMode(dataTransfer)) {
25678
            dataTransferImpl.setData(format, data);
25679
          }
25680
        },
25681
        clearData: format => {
25682
          if (isInReadWriteMode(dataTransfer)) {
25683
            dataTransferImpl.clearData(format);
25684
          }
25685
        }
25686
      };
25687
      setReadWriteMode(dataTransfer);
25688
      return dataTransfer;
25689
    };
25690
    const cloneDataTransfer = original => {
25691
      const clone = createDataTransfer();
25692
      const originalMode = getMode(original);
25693
      setReadOnlyMode(original);
25694
      setDragstartEvent(clone);
25695
      clone.dropEffect = original.dropEffect;
25696
      clone.effectAllowed = original.effectAllowed;
25697
      getDragImage(original).each(imageData => clone.setDragImage(imageData.image, imageData.x, imageData.y));
25698
      each$e(original.types, type => {
25699
        if (type !== 'Files') {
25700
          clone.setData(type, original.getData(type));
25701
        }
25702
      });
25703
      each$e(original.files, file => clone.items.add(file));
25704
      getEvent(original).each(type => {
25705
        setEvent(clone, type);
25706
      });
25707
      originalMode.each(mode => {
25708
        setMode$1(original, mode);
25709
        setMode$1(clone, mode);
25710
      });
25711
      return clone;
25712
    };
25713
 
25714
    const getHtmlData = dataTransfer => {
25715
      const html = dataTransfer.getData('text/html');
25716
      return html === '' ? Optional.none() : Optional.some(html);
25717
    };
25718
    const setHtmlData = (dataTransfer, html) => dataTransfer.setData('text/html', html);
25719
 
25720
    const internalMimeType = 'x-tinymce/html';
25721
    const internalHtmlMime = constant(internalMimeType);
25722
    const internalMark = '<!-- ' + internalMimeType + ' -->';
25723
    const mark = html => internalMark + html;
25724
    const unmark = html => html.replace(internalMark, '');
25725
    const isMarked = html => html.indexOf(internalMark) !== -1;
25726
 
25727
    const isPlainText = text => {
25728
      return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text);
25729
    };
25730
    const openContainer = (rootTag, rootAttrs) => {
25731
      let tag = '<' + rootTag;
25732
      const attrs = mapToArray(rootAttrs, (value, key) => key + '="' + Entities.encodeAllRaw(value) + '"');
25733
      if (attrs.length) {
25734
        tag += ' ' + attrs.join(' ');
25735
      }
25736
      return tag + '>';
25737
    };
25738
    const toBlockElements = (text, rootTag, rootAttrs) => {
25739
      const blocks = text.split(/\n\n/);
25740
      const tagOpen = openContainer(rootTag, rootAttrs);
25741
      const tagClose = '</' + rootTag + '>';
25742
      const paragraphs = map$3(blocks, p => {
25743
        return p.split(/\n/).join('<br />');
25744
      });
25745
      const stitch = p => {
25746
        return tagOpen + p + tagClose;
25747
      };
25748
      return paragraphs.length === 1 ? paragraphs[0] : map$3(paragraphs, stitch).join('');
25749
    };
25750
 
25751
    const pasteBinDefaultContent = '%MCEPASTEBIN%';
25752
    const create$6 = (editor, lastRngCell) => {
25753
      const {dom, selection} = editor;
25754
      const body = editor.getBody();
25755
      lastRngCell.set(selection.getRng());
25756
      const pasteBinElm = dom.add(editor.getBody(), 'div', {
25757
        'id': 'mcepastebin',
25758
        'class': 'mce-pastebin',
25759
        'contentEditable': true,
25760
        'data-mce-bogus': 'all',
25761
        'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0'
25762
      }, pasteBinDefaultContent);
25763
      if (Env.browser.isFirefox()) {
25764
        dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535);
25765
      }
25766
      dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', e => {
25767
        e.stopPropagation();
25768
      });
25769
      pasteBinElm.focus();
25770
      selection.select(pasteBinElm, true);
25771
    };
25772
    const remove = (editor, lastRngCell) => {
25773
      const dom = editor.dom;
25774
      if (getEl(editor)) {
25775
        let pasteBinClone;
25776
        const lastRng = lastRngCell.get();
25777
        while (pasteBinClone = getEl(editor)) {
25778
          dom.remove(pasteBinClone);
25779
          dom.unbind(pasteBinClone);
25780
        }
25781
        if (lastRng) {
25782
          editor.selection.setRng(lastRng);
25783
        }
25784
      }
25785
      lastRngCell.set(null);
25786
    };
25787
    const getEl = editor => editor.dom.get('mcepastebin');
25788
    const isPasteBin = elm => isNonNullable(elm) && elm.id === 'mcepastebin';
25789
    const getHtml = editor => {
25790
      const dom = editor.dom;
25791
      const copyAndRemove = (toElm, fromElm) => {
25792
        toElm.appendChild(fromElm);
25793
        dom.remove(fromElm, true);
25794
      };
25795
      const [pasteBinElm, ...pasteBinClones] = filter$5(editor.getBody().childNodes, isPasteBin);
25796
      each$e(pasteBinClones, pasteBinClone => {
25797
        copyAndRemove(pasteBinElm, pasteBinClone);
25798
      });
25799
      const dirtyWrappers = dom.select('div[id=mcepastebin]', pasteBinElm);
25800
      for (let i = dirtyWrappers.length - 1; i >= 0; i--) {
25801
        const cleanWrapper = dom.create('div');
25802
        pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]);
25803
        copyAndRemove(cleanWrapper, dirtyWrappers[i]);
25804
      }
25805
      return pasteBinElm ? pasteBinElm.innerHTML : '';
25806
    };
25807
    const isDefaultPasteBinContent = content => content === pasteBinDefaultContent;
25808
    const PasteBin = editor => {
25809
      const lastRng = Cell(null);
25810
      return {
25811
        create: () => create$6(editor, lastRng),
25812
        remove: () => remove(editor, lastRng),
25813
        getEl: () => getEl(editor),
25814
        getHtml: () => getHtml(editor),
25815
        getLastRng: lastRng.get
25816
      };
25817
    };
25818
 
25819
    const filter$1 = (content, items) => {
25820
      Tools.each(items, v => {
25821
        if (is$4(v, RegExp)) {
25822
          content = content.replace(v, '');
25823
        } else {
25824
          content = content.replace(v[0], v[1]);
25825
        }
25826
      });
25827
      return content;
25828
    };
25829
    const innerText = html => {
25830
      const schema = Schema();
25831
      const domParser = DomParser({}, schema);
25832
      let text = '';
25833
      const voidElements = schema.getVoidElements();
25834
      const ignoreElements = Tools.makeMap('script noscript style textarea video audio iframe object', ' ');
25835
      const blockElements = schema.getBlockElements();
25836
      const walk = node => {
25837
        const name = node.name, currentNode = node;
25838
        if (name === 'br') {
25839
          text += '\n';
25840
          return;
25841
        }
25842
        if (name === 'wbr') {
25843
          return;
25844
        }
25845
        if (voidElements[name]) {
25846
          text += ' ';
25847
        }
25848
        if (ignoreElements[name]) {
25849
          text += ' ';
25850
          return;
25851
        }
25852
        if (node.type === 3) {
25853
          text += node.value;
25854
        }
25855
        if (!(node.name in schema.getVoidElements())) {
25856
          let currentNode = node.firstChild;
25857
          if (currentNode) {
25858
            do {
25859
              walk(currentNode);
25860
            } while (currentNode = currentNode.next);
25861
          }
25862
        }
25863
        if (blockElements[name] && currentNode.next) {
25864
          text += '\n';
25865
          if (name === 'p') {
25866
            text += '\n';
25867
          }
25868
        }
25869
      };
25870
      html = filter$1(html, [/<!\[[^\]]+\]>/g]);
25871
      walk(domParser.parse(html));
25872
      return text;
25873
    };
25874
    const trimHtml = html => {
25875
      const trimSpaces = (all, s1, s2) => {
25876
        if (!s1 && !s2) {
25877
          return ' ';
25878
        }
25879
        return nbsp;
25880
      };
25881
      html = filter$1(html, [
25882
        /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig,
25883
        /<!--StartFragment-->|<!--EndFragment-->/g,
25884
        [
25885
          /( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g,
25886
          trimSpaces
25887
        ],
25888
        /<br class="Apple-interchange-newline">/g,
25889
        /<br>$/i
25890
      ]);
25891
      return html;
25892
    };
25893
    const createIdGenerator = prefix => {
25894
      let count = 0;
25895
      return () => {
25896
        return prefix + count++;
25897
      };
25898
    };
25899
    const getImageMimeType = ext => {
25900
      const lowerExt = ext.toLowerCase();
25901
      const mimeOverrides = {
25902
        jpg: 'jpeg',
25903
        jpe: 'jpeg',
25904
        jfi: 'jpeg',
25905
        jif: 'jpeg',
25906
        jfif: 'jpeg',
25907
        pjpeg: 'jpeg',
25908
        pjp: 'jpeg',
25909
        svg: 'svg+xml'
25910
      };
25911
      return Tools.hasOwn(mimeOverrides, lowerExt) ? 'image/' + mimeOverrides[lowerExt] : 'image/' + lowerExt;
25912
    };
25913
 
25914
    const preProcess = (editor, html) => {
25915
      const parser = DomParser({
25916
        sanitize: shouldSanitizeXss(editor),
25917
        sandbox_iframes: shouldSandboxIframes(editor)
25918
      }, editor.schema);
25919
      parser.addNodeFilter('meta', nodes => {
25920
        Tools.each(nodes, node => {
25921
          node.remove();
25922
        });
25923
      });
25924
      const fragment = parser.parse(html, {
25925
        forced_root_block: false,
25926
        isRootContent: true
25927
      });
25928
      return HtmlSerializer({ validate: true }, editor.schema).serialize(fragment);
25929
    };
25930
    const processResult = (content, cancelled) => ({
25931
      content,
25932
      cancelled
25933
    });
25934
    const postProcessFilter = (editor, html, internal) => {
25935
      const tempBody = editor.dom.create('div', { style: 'display:none' }, html);
25936
      const postProcessArgs = firePastePostProcess(editor, tempBody, internal);
25937
      return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented());
25938
    };
25939
    const filterContent = (editor, content, internal) => {
25940
      const preProcessArgs = firePastePreProcess(editor, content, internal);
25941
      const filteredContent = preProcess(editor, preProcessArgs.content);
25942
      if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) {
25943
        return postProcessFilter(editor, filteredContent, internal);
25944
      } else {
25945
        return processResult(filteredContent, preProcessArgs.isDefaultPrevented());
25946
      }
25947
    };
25948
    const process = (editor, html, internal) => {
25949
      return filterContent(editor, html, internal);
25950
    };
25951
 
25952
    const pasteHtml$1 = (editor, html) => {
25953
      editor.insertContent(html, {
25954
        merge: shouldPasteMergeFormats(editor),
25955
        paste: true
25956
      });
25957
      return true;
25958
    };
25959
    const isAbsoluteUrl = url => /^https?:\/\/[\w\-\/+=.,!;:&%@^~(){}?#]+$/i.test(url);
25960
    const isImageUrl = (editor, url) => {
25961
      return isAbsoluteUrl(url) && exists(getAllowedImageFileTypes(editor), type => endsWith(url.toLowerCase(), `.${ type.toLowerCase() }`));
25962
    };
25963
    const createImage = (editor, url, pasteHtmlFn) => {
25964
      editor.undoManager.extra(() => {
25965
        pasteHtmlFn(editor, url);
25966
      }, () => {
25967
        editor.insertContent('<img src="' + url + '">');
25968
      });
25969
      return true;
25970
    };
25971
    const createLink = (editor, url, pasteHtmlFn) => {
25972
      editor.undoManager.extra(() => {
25973
        pasteHtmlFn(editor, url);
25974
      }, () => {
25975
        editor.execCommand('mceInsertLink', false, url);
25976
      });
25977
      return true;
25978
    };
25979
    const linkSelection = (editor, html, pasteHtmlFn) => !editor.selection.isCollapsed() && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false;
25980
    const insertImage = (editor, html, pasteHtmlFn) => isImageUrl(editor, html) ? createImage(editor, html, pasteHtmlFn) : false;
25981
    const smartInsertContent = (editor, html) => {
25982
      Tools.each([
25983
        linkSelection,
25984
        insertImage,
25985
        pasteHtml$1
25986
      ], action => {
25987
        return !action(editor, html, pasteHtml$1);
25988
      });
25989
    };
25990
    const insertContent = (editor, html, pasteAsText) => {
25991
      if (pasteAsText || !isSmartPasteEnabled(editor)) {
25992
        pasteHtml$1(editor, html);
25993
      } else {
25994
        smartInsertContent(editor, html);
25995
      }
25996
    };
25997
 
25998
    const uniqueId = createIdGenerator('mceclip');
25999
    const createPasteDataTransfer = html => {
26000
      const dataTransfer = createDataTransfer();
26001
      setHtmlData(dataTransfer, html);
26002
      setReadOnlyMode(dataTransfer);
26003
      return dataTransfer;
26004
    };
26005
    const doPaste = (editor, content, internal, pasteAsText, shouldSimulateInputEvent) => {
26006
      const res = process(editor, content, internal);
26007
      if (!res.cancelled) {
26008
        const content = res.content;
26009
        const doPasteAction = () => insertContent(editor, content, pasteAsText);
26010
        if (shouldSimulateInputEvent) {
26011
          const args = fireBeforeInputEvent(editor, 'insertFromPaste', { dataTransfer: createPasteDataTransfer(content) });
26012
          if (!args.isDefaultPrevented()) {
26013
            doPasteAction();
26014
            fireInputEvent(editor, 'insertFromPaste');
26015
          }
26016
        } else {
26017
          doPasteAction();
26018
        }
26019
      }
26020
    };
26021
    const pasteHtml = (editor, html, internalFlag, shouldSimulateInputEvent) => {
26022
      const internal = internalFlag ? internalFlag : isMarked(html);
26023
      doPaste(editor, unmark(html), internal, false, shouldSimulateInputEvent);
26024
    };
26025
    const pasteText = (editor, text, shouldSimulateInputEvent) => {
26026
      const encodedText = editor.dom.encode(text).replace(/\r\n/g, '\n');
26027
      const normalizedText = normalize$4(encodedText, getPasteTabSpaces(editor));
26028
      const html = toBlockElements(normalizedText, getForcedRootBlock(editor), getForcedRootBlockAttrs(editor));
26029
      doPaste(editor, html, false, true, shouldSimulateInputEvent);
26030
    };
26031
    const getDataTransferItems = dataTransfer => {
26032
      const items = {};
26033
      if (dataTransfer && dataTransfer.types) {
26034
        for (let i = 0; i < dataTransfer.types.length; i++) {
26035
          const contentType = dataTransfer.types[i];
26036
          try {
26037
            items[contentType] = dataTransfer.getData(contentType);
26038
          } catch (ex) {
26039
            items[contentType] = '';
26040
          }
26041
        }
26042
      }
26043
      return items;
26044
    };
26045
    const hasContentType = (clipboardContent, mimeType) => mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
26046
    const hasHtmlOrText = content => hasContentType(content, 'text/html') || hasContentType(content, 'text/plain');
26047
    const extractFilename = (editor, str) => {
26048
      const m = str.match(/([\s\S]+?)(?:\.[a-z0-9.]+)$/i);
26049
      return isNonNullable(m) ? editor.dom.encode(m[1]) : undefined;
26050
    };
26051
    const createBlobInfo = (editor, blobCache, file, base64) => {
26052
      const id = uniqueId();
26053
      const useFileName = shouldReuseFileName(editor) && isNonNullable(file.name);
26054
      const name = useFileName ? extractFilename(editor, file.name) : id;
26055
      const filename = useFileName ? file.name : undefined;
26056
      const blobInfo = blobCache.create(id, file, base64, name, filename);
26057
      blobCache.add(blobInfo);
26058
      return blobInfo;
26059
    };
26060
    const pasteImage = (editor, imageItem) => {
26061
      parseDataUri(imageItem.uri).each(({data, type, base64Encoded}) => {
26062
        const base64 = base64Encoded ? data : btoa(data);
26063
        const file = imageItem.file;
26064
        const blobCache = editor.editorUpload.blobCache;
26065
        const existingBlobInfo = blobCache.getByData(base64, type);
26066
        const blobInfo = existingBlobInfo !== null && existingBlobInfo !== void 0 ? existingBlobInfo : createBlobInfo(editor, blobCache, file, base64);
26067
        pasteHtml(editor, `<img src="${ blobInfo.blobUri() }">`, false, true);
26068
      });
26069
    };
26070
    const isClipboardEvent = event => event.type === 'paste';
26071
    const readFilesAsDataUris = items => Promise.all(map$3(items, file => {
26072
      return blobToDataUri(file).then(uri => ({
26073
        file,
26074
        uri
26075
      }));
26076
    }));
26077
    const isImage = editor => {
26078
      const allowedExtensions = getAllowedImageFileTypes(editor);
26079
      return file => startsWith(file.type, 'image/') && exists(allowedExtensions, extension => {
26080
        return getImageMimeType(extension) === file.type;
26081
      });
26082
    };
26083
    const getImagesFromDataTransfer = (editor, dataTransfer) => {
26084
      const items = dataTransfer.items ? bind$3(from(dataTransfer.items), item => {
26085
        return item.kind === 'file' ? [item.getAsFile()] : [];
26086
      }) : [];
26087
      const files = dataTransfer.files ? from(dataTransfer.files) : [];
26088
      return filter$5(items.length > 0 ? items : files, isImage(editor));
26089
    };
26090
    const pasteImageData = (editor, e, rng) => {
26091
      const dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer;
26092
      if (shouldPasteDataImages(editor) && dataTransfer) {
26093
        const images = getImagesFromDataTransfer(editor, dataTransfer);
26094
        if (images.length > 0) {
26095
          e.preventDefault();
26096
          readFilesAsDataUris(images).then(fileResults => {
26097
            if (rng) {
26098
              editor.selection.setRng(rng);
26099
            }
26100
            each$e(fileResults, result => {
26101
              pasteImage(editor, result);
26102
            });
26103
          });
26104
          return true;
26105
        }
26106
      }
26107
      return false;
26108
    };
26109
    const isBrokenAndroidClipboardEvent = e => {
26110
      var _a, _b;
26111
      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;
26112
    };
26113
    const isKeyboardPasteEvent = e => VK.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45;
26114
    const insertClipboardContent = (editor, clipboardContent, html, plainTextMode, shouldSimulateInputEvent) => {
26115
      let content = trimHtml(html);
26116
      const isInternal = hasContentType(clipboardContent, internalHtmlMime()) || isMarked(html);
26117
      const isPlainTextHtml = !isInternal && isPlainText(content);
26118
      const isAbsoluteUrl$1 = isAbsoluteUrl(content);
26119
      if (isDefaultPasteBinContent(content) || !content.length || isPlainTextHtml && !isAbsoluteUrl$1) {
26120
        plainTextMode = true;
26121
      }
26122
      if (plainTextMode || isAbsoluteUrl$1) {
26123
        if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) {
26124
          content = clipboardContent['text/plain'];
26125
        } else {
26126
          content = innerText(content);
26127
        }
26128
      }
26129
      if (isDefaultPasteBinContent(content)) {
26130
        return;
26131
      }
26132
      if (plainTextMode) {
26133
        pasteText(editor, content, shouldSimulateInputEvent);
26134
      } else {
26135
        pasteHtml(editor, content, isInternal, shouldSimulateInputEvent);
26136
      }
26137
    };
26138
    const registerEventHandlers = (editor, pasteBin, pasteFormat) => {
26139
      let keyboardPastePlainTextState;
26140
      const getLastRng = () => pasteBin.getLastRng() || editor.selection.getRng();
26141
      editor.on('keydown', e => {
26142
        if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
26143
          keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86;
26144
        }
26145
      });
26146
      editor.on('paste', e => {
26147
        if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
26148
          return;
26149
        }
26150
        const plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState;
26151
        keyboardPastePlainTextState = false;
26152
        const clipboardContent = getDataTransferItems(e.clipboardData);
26153
        if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) {
26154
          return;
26155
        }
26156
        if (hasContentType(clipboardContent, 'text/html')) {
26157
          e.preventDefault();
26158
          insertClipboardContent(editor, clipboardContent, clipboardContent['text/html'], plainTextMode, true);
26159
        } else if (hasContentType(clipboardContent, 'text/plain') && hasContentType(clipboardContent, 'text/uri-list')) {
26160
          e.preventDefault();
26161
          insertClipboardContent(editor, clipboardContent, clipboardContent['text/plain'], plainTextMode, true);
26162
        } else {
26163
          pasteBin.create();
26164
          Delay.setEditorTimeout(editor, () => {
26165
            const html = pasteBin.getHtml();
26166
            pasteBin.remove();
26167
            insertClipboardContent(editor, clipboardContent, html, plainTextMode, false);
26168
          }, 0);
26169
        }
26170
      });
26171
    };
26172
    const registerDataImageFilter = editor => {
26173
      const isWebKitFakeUrl = src => startsWith(src, 'webkit-fake-url');
26174
      const isDataUri = src => startsWith(src, 'data:');
26175
      const isPasteInsert = args => {
26176
        var _a;
26177
        return ((_a = args.data) === null || _a === void 0 ? void 0 : _a.paste) === true;
26178
      };
26179
      editor.parser.addNodeFilter('img', (nodes, name, args) => {
26180
        if (!shouldPasteDataImages(editor) && isPasteInsert(args)) {
26181
          for (const node of nodes) {
26182
            const src = node.attr('src');
26183
            if (isString(src) && !node.attr('data-mce-object') && src !== Env.transparentSrc) {
26184
              if (isWebKitFakeUrl(src)) {
26185
                node.remove();
26186
              } else if (!shouldAllowHtmlDataUrls(editor) && isDataUri(src)) {
26187
                node.remove();
26188
              }
26189
            }
26190
          }
26191
        }
26192
      });
26193
    };
26194
    const registerEventsAndFilters = (editor, pasteBin, pasteFormat) => {
26195
      registerEventHandlers(editor, pasteBin, pasteFormat);
26196
      registerDataImageFilter(editor);
26197
    };
26198
 
26199
    const togglePlainTextPaste = (editor, pasteFormat) => {
26200
      if (pasteFormat.get() === 'text') {
26201
        pasteFormat.set('html');
26202
        firePastePlainTextToggle(editor, false);
26203
      } else {
26204
        pasteFormat.set('text');
26205
        firePastePlainTextToggle(editor, true);
26206
      }
26207
      editor.focus();
26208
    };
26209
    const register$1 = (editor, pasteFormat) => {
26210
      editor.addCommand('mceTogglePlainTextPaste', () => {
26211
        togglePlainTextPaste(editor, pasteFormat);
26212
      });
26213
      editor.addCommand('mceInsertClipboardContent', (ui, value) => {
26214
        if (value.html) {
26215
          pasteHtml(editor, value.html, value.internal, false);
26216
        }
26217
        if (value.text) {
26218
          pasteText(editor, value.text, false);
26219
        }
26220
      });
26221
    };
26222
 
26223
    const setHtml5Clipboard = (clipboardData, html, text) => {
26224
      if (clipboardData) {
26225
        try {
26226
          clipboardData.clearData();
26227
          clipboardData.setData('text/html', html);
26228
          clipboardData.setData('text/plain', text);
26229
          clipboardData.setData(internalHtmlMime(), html);
26230
          return true;
26231
        } catch (e) {
26232
          return false;
26233
        }
26234
      } else {
26235
        return false;
26236
      }
26237
    };
26238
    const setClipboardData = (evt, data, fallback, done) => {
26239
      if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) {
26240
        evt.preventDefault();
26241
        done();
26242
      } else {
26243
        fallback(data.html, done);
26244
      }
26245
    };
26246
    const fallback = editor => (html, done) => {
26247
      const {dom, selection} = editor;
26248
      const outer = dom.create('div', {
26249
        'contenteditable': 'false',
26250
        'data-mce-bogus': 'all'
26251
      });
26252
      const inner = dom.create('div', { contenteditable: 'true' }, html);
26253
      dom.setStyles(outer, {
26254
        position: 'fixed',
26255
        top: '0',
26256
        left: '-3000px',
26257
        width: '1000px',
26258
        overflow: 'hidden'
26259
      });
26260
      outer.appendChild(inner);
26261
      dom.add(editor.getBody(), outer);
26262
      const range = selection.getRng();
26263
      inner.focus();
26264
      const offscreenRange = dom.createRng();
26265
      offscreenRange.selectNodeContents(inner);
26266
      selection.setRng(offscreenRange);
26267
      Delay.setEditorTimeout(editor, () => {
26268
        selection.setRng(range);
26269
        dom.remove(outer);
26270
        done();
26271
      }, 0);
26272
    };
26273
    const getData = editor => ({
26274
      html: mark(editor.selection.getContent({ contextual: true })),
26275
      text: editor.selection.getContent({ format: 'text' })
26276
    });
26277
    const isTableSelection = editor => !!editor.dom.getParent(editor.selection.getStart(), 'td[data-mce-selected],th[data-mce-selected]', editor.getBody());
26278
    const hasSelectedContent = editor => !editor.selection.isCollapsed() || isTableSelection(editor);
26279
    const cut = editor => evt => {
26280
      if (!evt.isDefaultPrevented() && hasSelectedContent(editor) && editor.selection.isEditable()) {
26281
        setClipboardData(evt, getData(editor), fallback(editor), () => {
26282
          if (Env.browser.isChromium() || Env.browser.isFirefox()) {
26283
            const rng = editor.selection.getRng();
26284
            Delay.setEditorTimeout(editor, () => {
26285
              editor.selection.setRng(rng);
26286
              editor.execCommand('Delete');
26287
            }, 0);
26288
          } else {
26289
            editor.execCommand('Delete');
26290
          }
26291
        });
26292
      }
26293
    };
26294
    const copy = editor => evt => {
26295
      if (!evt.isDefaultPrevented() && hasSelectedContent(editor)) {
26296
        setClipboardData(evt, getData(editor), fallback(editor), noop);
26297
      }
26298
    };
26299
    const register = editor => {
26300
      editor.on('cut', cut(editor));
26301
      editor.on('copy', copy(editor));
26302
    };
26303
 
26304
    const getCaretRangeFromEvent = (editor, e) => {
26305
      var _a, _b;
26306
      return RangeUtils.getCaretRangeFromPoint((_a = e.clientX) !== null && _a !== void 0 ? _a : 0, (_b = e.clientY) !== null && _b !== void 0 ? _b : 0, editor.getDoc());
26307
    };
26308
    const isPlainTextFileUrl = content => {
26309
      const plainTextContent = content['text/plain'];
26310
      return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false;
26311
    };
26312
    const setFocusedRange = (editor, rng) => {
26313
      editor.focus();
26314
      if (rng) {
26315
        editor.selection.setRng(rng);
26316
      }
26317
    };
26318
    const hasImage = dataTransfer => exists(dataTransfer.files, file => /^image\//.test(file.type));
26319
    const needsCustomInternalDrop = (dom, schema, target, dropContent) => {
26320
      const parentTransparent = dom.getParent(target, node => isTransparentBlock(schema, node));
26321
      const inSummary = !isNull(dom.getParent(target, 'summary'));
26322
      if (inSummary) {
26323
        return true;
26324
      } else if (parentTransparent && has$2(dropContent, 'text/html')) {
26325
        const fragment = new DOMParser().parseFromString(dropContent['text/html'], 'text/html').body;
26326
        return !isNull(fragment.querySelector(parentTransparent.nodeName.toLowerCase()));
26327
      } else {
26328
        return false;
26329
      }
26330
    };
26331
    const setupSummaryDeleteByDragFix = editor => {
26332
      editor.on('input', e => {
26333
        const hasNoSummary = el => isNull(el.querySelector('summary'));
26334
        if (e.inputType === 'deleteByDrag') {
26335
          const brokenDetailElements = filter$5(editor.dom.select('details'), hasNoSummary);
26336
          each$e(brokenDetailElements, details => {
26337
            if (isBr$6(details.firstChild)) {
26338
              details.firstChild.remove();
26339
            }
26340
            const summary = editor.dom.create('summary');
26341
            summary.appendChild(createPaddingBr().dom);
26342
            details.prepend(summary);
26343
          });
26344
        }
26345
      });
26346
    };
26347
    const setup$a = (editor, draggingInternallyState) => {
26348
      if (shouldPasteBlockDrop(editor)) {
26349
        editor.on('dragend dragover draggesture dragdrop drop drag', e => {
26350
          e.preventDefault();
26351
          e.stopPropagation();
26352
        });
26353
      }
26354
      if (!shouldPasteDataImages(editor)) {
26355
        editor.on('drop', e => {
26356
          const dataTransfer = e.dataTransfer;
26357
          if (dataTransfer && hasImage(dataTransfer)) {
26358
            e.preventDefault();
26359
          }
26360
        });
26361
      }
26362
      editor.on('drop', e => {
26363
        if (e.isDefaultPrevented()) {
26364
          return;
26365
        }
26366
        const rng = getCaretRangeFromEvent(editor, e);
26367
        if (isNullable(rng)) {
26368
          return;
26369
        }
26370
        const dropContent = getDataTransferItems(e.dataTransfer);
26371
        const internal = hasContentType(dropContent, internalHtmlMime());
26372
        if ((!hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && pasteImageData(editor, e, rng)) {
26373
          return;
26374
        }
26375
        const internalContent = dropContent[internalHtmlMime()];
26376
        const content = internalContent || dropContent['text/html'] || dropContent['text/plain'];
26377
        const needsInternalDrop = needsCustomInternalDrop(editor.dom, editor.schema, rng.startContainer, dropContent);
26378
        const isInternalDrop = draggingInternallyState.get();
26379
        if (isInternalDrop && !needsInternalDrop) {
26380
          return;
26381
        }
26382
        if (content) {
26383
          e.preventDefault();
26384
          Delay.setEditorTimeout(editor, () => {
26385
            editor.undoManager.transact(() => {
26386
              if (internalContent || isInternalDrop && needsInternalDrop) {
26387
                editor.execCommand('Delete');
26388
              }
26389
              setFocusedRange(editor, rng);
26390
              const trimmedContent = trimHtml(content);
26391
              if (dropContent['text/html']) {
26392
                pasteHtml(editor, trimmedContent, internal, true);
26393
              } else {
26394
                pasteText(editor, trimmedContent, true);
26395
              }
26396
            });
26397
          });
26398
        }
26399
      });
26400
      editor.on('dragstart', _e => {
26401
        draggingInternallyState.set(true);
26402
      });
26403
      editor.on('dragover dragend', e => {
26404
        if (shouldPasteDataImages(editor) && !draggingInternallyState.get()) {
26405
          e.preventDefault();
26406
          setFocusedRange(editor, getCaretRangeFromEvent(editor, e));
26407
        }
26408
        if (e.type === 'dragend') {
26409
          draggingInternallyState.set(false);
26410
        }
26411
      });
26412
      setupSummaryDeleteByDragFix(editor);
26413
    };
26414
 
26415
    const setup$9 = editor => {
26416
      const processEvent = f => e => {
26417
        f(editor, e);
26418
      };
26419
      const preProcess = getPastePreProcess(editor);
26420
      if (isFunction(preProcess)) {
26421
        editor.on('PastePreProcess', processEvent(preProcess));
26422
      }
26423
      const postProcess = getPastePostProcess(editor);
26424
      if (isFunction(postProcess)) {
26425
        editor.on('PastePostProcess', processEvent(postProcess));
26426
      }
26427
    };
26428
 
26429
    const addPreProcessFilter = (editor, filterFunc) => {
26430
      editor.on('PastePreProcess', e => {
26431
        e.content = filterFunc(editor, e.content, e.internal);
26432
      });
26433
    };
26434
    const rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi;
26435
    const rgbToHex = value => Tools.trim(value).replace(rgbRegExp, rgbaToHexString).toLowerCase();
26436
    const removeWebKitStyles = (editor, content, internal) => {
26437
      const webKitStylesOption = getPasteWebkitStyles(editor);
26438
      if (internal || webKitStylesOption === 'all' || !shouldPasteRemoveWebKitStyles(editor)) {
26439
        return content;
26440
      }
26441
      const webKitStyles = webKitStylesOption ? webKitStylesOption.split(/[, ]/) : [];
26442
      if (webKitStyles && webKitStylesOption !== 'none') {
26443
        const dom = editor.dom, node = editor.selection.getNode();
26444
        content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, (all, before, value, after) => {
26445
          const inputStyles = dom.parseStyle(dom.decode(value));
26446
          const outputStyles = {};
26447
          for (let i = 0; i < webKitStyles.length; i++) {
26448
            const inputValue = inputStyles[webKitStyles[i]];
26449
            let compareInput = inputValue;
26450
            let currentValue = dom.getStyle(node, webKitStyles[i], true);
26451
            if (/color/.test(webKitStyles[i])) {
26452
              compareInput = rgbToHex(compareInput);
26453
              currentValue = rgbToHex(currentValue);
26454
            }
26455
            if (currentValue !== compareInput) {
26456
              outputStyles[webKitStyles[i]] = inputValue;
26457
            }
26458
          }
26459
          const outputStyle = dom.serializeStyle(outputStyles, 'span');
26460
          if (outputStyle) {
26461
            return before + ' style="' + outputStyle + '"' + after;
26462
          }
26463
          return before + after;
26464
        });
26465
      } else {
26466
        content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3');
26467
      }
26468
      content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, (all, before, value, after) => {
26469
        return before + ' style="' + value + '"' + after;
26470
      });
26471
      return content;
26472
    };
26473
    const setup$8 = editor => {
26474
      if (Env.browser.isChromium() || Env.browser.isSafari()) {
26475
        addPreProcessFilter(editor, removeWebKitStyles);
26476
      }
26477
    };
26478
 
26479
    const setup$7 = editor => {
26480
      const draggingInternallyState = Cell(false);
26481
      const pasteFormat = Cell(isPasteAsTextEnabled(editor) ? 'text' : 'html');
26482
      const pasteBin = PasteBin(editor);
26483
      setup$8(editor);
26484
      register$1(editor, pasteFormat);
26485
      setup$9(editor);
26486
      editor.on('PreInit', () => {
26487
        register(editor);
26488
        setup$a(editor, draggingInternallyState);
26489
        registerEventsAndFilters(editor, pasteBin, pasteFormat);
26490
      });
26491
    };
26492
 
26493
    const preventSummaryToggle = editor => {
26494
      editor.on('click', e => {
26495
        if (editor.dom.getParent(e.target, 'details')) {
26496
          e.preventDefault();
26497
        }
26498
      });
26499
    };
26500
    const filterDetails = editor => {
26501
      editor.parser.addNodeFilter('details', elms => {
26502
        const initialStateOption = getDetailsInitialState(editor);
26503
        each$e(elms, details => {
26504
          if (initialStateOption === 'expanded') {
26505
            details.attr('open', 'open');
26506
          } else if (initialStateOption === 'collapsed') {
26507
            details.attr('open', null);
26508
          }
26509
        });
26510
      });
26511
      editor.serializer.addNodeFilter('details', elms => {
26512
        const serializedStateOption = getDetailsSerializedState(editor);
26513
        each$e(elms, details => {
26514
          if (serializedStateOption === 'expanded') {
26515
            details.attr('open', 'open');
26516
          } else if (serializedStateOption === 'collapsed') {
26517
            details.attr('open', null);
26518
          }
26519
        });
26520
      });
26521
    };
26522
    const setup$6 = editor => {
26523
      preventSummaryToggle(editor);
26524
      filterDetails(editor);
26525
    };
26526
 
26527
    const isBr = isBr$6;
26528
    const isText = isText$a;
26529
    const isContentEditableFalse$2 = elm => isContentEditableFalse$b(elm.dom);
26530
    const isContentEditableTrue = elm => isContentEditableTrue$3(elm.dom);
26531
    const isRoot = rootNode => elm => eq(SugarElement.fromDom(rootNode), elm);
26532
    const getClosestScope = (node, rootNode, schema) => closest$4(SugarElement.fromDom(node), elm => isContentEditableTrue(elm) || schema.isBlock(name(elm)), isRoot(rootNode)).getOr(SugarElement.fromDom(rootNode)).dom;
26533
    const getClosestCef = (node, rootNode) => closest$4(SugarElement.fromDom(node), isContentEditableFalse$2, isRoot(rootNode));
26534
    const findEdgeCaretCandidate = (startNode, scope, forward) => {
26535
      const walker = new DomTreeWalker(startNode, scope);
26536
      const next = forward ? walker.next.bind(walker) : walker.prev.bind(walker);
26537
      let result = startNode;
26538
      for (let current = forward ? startNode : next(); current && !isBr(current); current = next()) {
26539
        if (isCaretCandidate$3(current)) {
26540
          result = current;
26541
        }
26542
      }
26543
      return result;
26544
    };
26545
    const findClosestBlockRange = (startRng, rootNode, schema) => {
26546
      const startPos = CaretPosition.fromRangeStart(startRng);
26547
      const clickNode = startPos.getNode();
26548
      const scope = getClosestScope(clickNode, rootNode, schema);
26549
      const startNode = findEdgeCaretCandidate(clickNode, scope, false);
26550
      const endNode = findEdgeCaretCandidate(clickNode, scope, true);
26551
      const rng = document.createRange();
26552
      getClosestCef(startNode, scope).fold(() => {
26553
        if (isText(startNode)) {
26554
          rng.setStart(startNode, 0);
26555
        } else {
26556
          rng.setStartBefore(startNode);
26557
        }
26558
      }, cef => rng.setStartBefore(cef.dom));
26559
      getClosestCef(endNode, scope).fold(() => {
26560
        if (isText(endNode)) {
26561
          rng.setEnd(endNode, endNode.data.length);
26562
        } else {
26563
          rng.setEndAfter(endNode);
26564
        }
26565
      }, cef => rng.setEndAfter(cef.dom));
26566
      return rng;
26567
    };
26568
    const onTripleClickSelect = editor => {
26569
      const rng = findClosestBlockRange(editor.selection.getRng(), editor.getBody(), editor.schema);
26570
      editor.selection.setRng(normalize(rng));
26571
    };
26572
    const setup$5 = editor => {
26573
      editor.on('mousedown', e => {
26574
        if (e.detail >= 3) {
26575
          e.preventDefault();
26576
          onTripleClickSelect(editor);
26577
        }
26578
      });
26579
    };
26580
 
26581
    var FakeCaretPosition;
26582
    (function (FakeCaretPosition) {
26583
      FakeCaretPosition['Before'] = 'before';
26584
      FakeCaretPosition['After'] = 'after';
26585
    }(FakeCaretPosition || (FakeCaretPosition = {})));
26586
    const distanceToRectLeft = (clientRect, clientX) => Math.abs(clientRect.left - clientX);
26587
    const distanceToRectRight = (clientRect, clientX) => Math.abs(clientRect.right - clientX);
26588
    const isInsideY = (clientY, clientRect) => clientY >= clientRect.top && clientY <= clientRect.bottom;
26589
    const collidesY = (r1, r2) => r1.top < r2.bottom && r1.bottom > r2.top;
26590
    const isOverlapping = (r1, r2) => {
26591
      const overlap = overlapY(r1, r2) / Math.min(r1.height, r2.height);
26592
      return collidesY(r1, r2) && overlap > 0.5;
26593
    };
26594
    const splitRectsPerAxis = (rects, y) => {
26595
      const intersectingRects = filter$5(rects, rect => isInsideY(y, rect));
26596
      return boundingClientRectFromRects(intersectingRects).fold(() => [
26597
        [],
26598
        rects
26599
      ], boundingRect => {
26600
        const {
26601
          pass: horizontal,
26602
          fail: vertical
26603
        } = partition$2(rects, rect => isOverlapping(rect, boundingRect));
26604
        return [
26605
          horizontal,
26606
          vertical
26607
        ];
26608
      });
26609
    };
26610
    const clientInfo = (rect, clientX) => {
26611
      return {
26612
        node: rect.node,
26613
        position: distanceToRectLeft(rect, clientX) < distanceToRectRight(rect, clientX) ? FakeCaretPosition.Before : FakeCaretPosition.After
26614
      };
26615
    };
26616
    const horizontalDistance = (rect, x, _y) => x > rect.left && x < rect.right ? 0 : Math.min(Math.abs(rect.left - x), Math.abs(rect.right - x));
26617
    const closestChildCaretCandidateNodeRect = (children, clientX, clientY, findCloserTextNode) => {
26618
      const caretCandidateRect = rect => {
26619
        if (isCaretCandidate$3(rect.node)) {
26620
          return Optional.some(rect);
26621
        } else if (isElement$6(rect.node)) {
26622
          return closestChildCaretCandidateNodeRect(from(rect.node.childNodes), clientX, clientY, false);
26623
        } else {
26624
          return Optional.none();
26625
        }
26626
      };
26627
      const tryFindSecondBestTextNode = (closest, sndClosest, distance) => {
26628
        return caretCandidateRect(sndClosest).filter(rect => {
26629
          const deltaDistance = Math.abs(distance(closest, clientX, clientY) - distance(rect, clientX, clientY));
26630
          return deltaDistance < 2 && isText$a(rect.node);
26631
        });
26632
      };
26633
      const findClosestCaretCandidateNodeRect = (rects, distance) => {
26634
        const sortedRects = sort(rects, (r1, r2) => distance(r1, clientX, clientY) - distance(r2, clientX, clientY));
26635
        return findMap(sortedRects, caretCandidateRect).map(closest => {
26636
          if (findCloserTextNode && !isText$a(closest.node) && sortedRects.length > 1) {
26637
            return tryFindSecondBestTextNode(closest, sortedRects[1], distance).getOr(closest);
26638
          } else {
26639
            return closest;
26640
          }
26641
        });
26642
      };
26643
      const [horizontalRects, verticalRects] = splitRectsPerAxis(getClientRects(children), clientY);
26644
      const {
26645
        pass: above,
26646
        fail: below
26647
      } = partition$2(verticalRects, rect => rect.top < clientY);
26648
      return findClosestCaretCandidateNodeRect(horizontalRects, horizontalDistance).orThunk(() => findClosestCaretCandidateNodeRect(below, distanceToRectEdgeFromXY)).orThunk(() => findClosestCaretCandidateNodeRect(above, distanceToRectEdgeFromXY));
26649
    };
26650
    const traverseUp = (rootElm, scope, clientX, clientY) => {
26651
      const helper = (scope, prevScope) => {
26652
        const isDragGhostContainer = node => isElement$6(node) && node.classList.contains('mce-drag-container');
26653
        const childNodesWithoutGhost = filter$5(scope.dom.childNodes, not(isDragGhostContainer));
26654
        return prevScope.fold(() => closestChildCaretCandidateNodeRect(childNodesWithoutGhost, clientX, clientY, true), prevScope => {
26655
          const uncheckedChildren = filter$5(childNodesWithoutGhost, node => node !== prevScope.dom);
26656
          return closestChildCaretCandidateNodeRect(uncheckedChildren, clientX, clientY, true);
26657
        }).orThunk(() => {
26658
          const parent = eq(scope, rootElm) ? Optional.none() : parentElement(scope);
26659
          return parent.bind(newScope => helper(newScope, Optional.some(scope)));
26660
        });
26661
      };
26662
      return helper(scope, Optional.none());
26663
    };
26664
    const closestCaretCandidateNodeRect = (root, clientX, clientY) => {
26665
      const rootElm = SugarElement.fromDom(root);
26666
      const ownerDoc = documentOrOwner(rootElm);
26667
      const elementAtPoint = SugarElement.fromPoint(ownerDoc, clientX, clientY).filter(elm => contains(rootElm, elm));
26668
      const element = elementAtPoint.getOr(rootElm);
26669
      return traverseUp(rootElm, element, clientX, clientY);
26670
    };
26671
    const closestFakeCaretCandidate = (root, clientX, clientY) => closestCaretCandidateNodeRect(root, clientX, clientY).filter(rect => isFakeCaretTarget(rect.node)).map(rect => clientInfo(rect, clientX));
26672
 
26673
    const getAbsolutePosition = elm => {
26674
      var _a, _b;
26675
      const clientRect = elm.getBoundingClientRect();
26676
      const doc = elm.ownerDocument;
26677
      const docElem = doc.documentElement;
26678
      const win = doc.defaultView;
26679
      return {
26680
        top: clientRect.top + ((_a = win === null || win === void 0 ? void 0 : win.scrollY) !== null && _a !== void 0 ? _a : 0) - docElem.clientTop,
26681
        left: clientRect.left + ((_b = win === null || win === void 0 ? void 0 : win.scrollX) !== null && _b !== void 0 ? _b : 0) - docElem.clientLeft
26682
      };
26683
    };
26684
    const getBodyPosition = editor => editor.inline ? getAbsolutePosition(editor.getBody()) : {
26685
      left: 0,
26686
      top: 0
26687
    };
26688
    const getScrollPosition = editor => {
26689
      const body = editor.getBody();
26690
      return editor.inline ? {
26691
        left: body.scrollLeft,
26692
        top: body.scrollTop
26693
      } : {
26694
        left: 0,
26695
        top: 0
26696
      };
26697
    };
26698
    const getBodyScroll = editor => {
26699
      const body = editor.getBody(), docElm = editor.getDoc().documentElement;
26700
      const inlineScroll = {
26701
        left: body.scrollLeft,
26702
        top: body.scrollTop
26703
      };
26704
      const iframeScroll = {
26705
        left: body.scrollLeft || docElm.scrollLeft,
26706
        top: body.scrollTop || docElm.scrollTop
26707
      };
26708
      return editor.inline ? inlineScroll : iframeScroll;
26709
    };
26710
    const getMousePosition = (editor, event) => {
26711
      if (event.target.ownerDocument !== editor.getDoc()) {
26712
        const iframePosition = getAbsolutePosition(editor.getContentAreaContainer());
26713
        const scrollPosition = getBodyScroll(editor);
26714
        return {
26715
          left: event.pageX - iframePosition.left + scrollPosition.left,
26716
          top: event.pageY - iframePosition.top + scrollPosition.top
26717
        };
26718
      }
26719
      return {
26720
        left: event.pageX,
26721
        top: event.pageY
26722
      };
26723
    };
26724
    const calculatePosition = (bodyPosition, scrollPosition, mousePosition) => ({
26725
      pageX: mousePosition.left - bodyPosition.left + scrollPosition.left,
26726
      pageY: mousePosition.top - bodyPosition.top + scrollPosition.top
26727
    });
26728
    const calc = (editor, event) => calculatePosition(getBodyPosition(editor), getScrollPosition(editor), getMousePosition(editor, event));
26729
 
26730
    const getTargetProps = target => ({
26731
      target,
26732
      srcElement: target
26733
    });
26734
    const makeDndEventFromMouseEvent = (type, mouseEvent, target, dataTransfer) => ({
26735
      ...mouseEvent,
26736
      dataTransfer,
26737
      type,
26738
      ...getTargetProps(target)
26739
    });
26740
    const makeDndEvent = (type, target, dataTransfer) => {
26741
      const fail = die('Function not supported on simulated event.');
26742
      const event = {
26743
        bubbles: true,
26744
        cancelBubble: false,
26745
        cancelable: true,
26746
        composed: false,
26747
        currentTarget: null,
26748
        defaultPrevented: false,
26749
        eventPhase: 0,
26750
        isTrusted: true,
26751
        returnValue: false,
26752
        timeStamp: 0,
26753
        type,
26754
        composedPath: fail,
26755
        initEvent: fail,
26756
        preventDefault: noop,
26757
        stopImmediatePropagation: noop,
26758
        stopPropagation: noop,
26759
        AT_TARGET: window.Event.AT_TARGET,
26760
        BUBBLING_PHASE: window.Event.BUBBLING_PHASE,
26761
        CAPTURING_PHASE: window.Event.CAPTURING_PHASE,
26762
        NONE: window.Event.NONE,
26763
        altKey: false,
26764
        button: 0,
26765
        buttons: 0,
26766
        clientX: 0,
26767
        clientY: 0,
26768
        ctrlKey: false,
26769
        metaKey: false,
26770
        movementX: 0,
26771
        movementY: 0,
26772
        offsetX: 0,
26773
        offsetY: 0,
26774
        pageX: 0,
26775
        pageY: 0,
26776
        relatedTarget: null,
26777
        screenX: 0,
26778
        screenY: 0,
26779
        shiftKey: false,
26780
        x: 0,
26781
        y: 0,
26782
        detail: 0,
26783
        view: null,
26784
        which: 0,
26785
        initUIEvent: fail,
26786
        initMouseEvent: fail,
26787
        getModifierState: fail,
26788
        dataTransfer,
26789
        ...getTargetProps(target)
26790
      };
26791
      return event;
26792
    };
26793
    const makeDataTransferCopyForDragEvent = (dataTransfer, eventType) => {
26794
      const copy = cloneDataTransfer(dataTransfer);
26795
      if (eventType === 'dragstart') {
26796
        setDragstartEvent(copy);
26797
        setReadWriteMode(copy);
26798
      } else if (eventType === 'drop') {
26799
        setDropEvent(copy);
26800
        setReadOnlyMode(copy);
26801
      } else {
26802
        setDragendEvent(copy);
26803
        setProtectedMode(copy);
26804
      }
26805
      return copy;
26806
    };
26807
    const makeDragEvent = (type, target, dataTransfer, mouseEvent) => {
26808
      const dataTransferForDispatch = makeDataTransferCopyForDragEvent(dataTransfer, type);
26809
      return isUndefined(mouseEvent) ? makeDndEvent(type, target, dataTransferForDispatch) : makeDndEventFromMouseEvent(type, mouseEvent, target, dataTransferForDispatch);
26810
    };
26811
 
26812
    const scrollPixelsPerInterval = 32;
26813
    const scrollIntervalValue = 100;
26814
    const mouseRangeToTriggerScrollInsideEditor = 8;
26815
    const mouseRangeToTriggerScrollOutsideEditor = 16;
26816
    const isContentEditableFalse$1 = isContentEditableFalse$b;
26817
    const isContentEditable = or(isContentEditableFalse$1, isContentEditableTrue$3);
26818
    const isDraggable = (dom, rootElm, elm) => isContentEditableFalse$1(elm) && elm !== rootElm && dom.isEditable(elm.parentElement);
26819
    const isValidDropTarget = (editor, targetElement, dragElement) => {
26820
      if (isNullable(targetElement)) {
26821
        return false;
26822
      } else if (targetElement === dragElement || editor.dom.isChildOf(targetElement, dragElement)) {
26823
        return false;
26824
      } else {
26825
        return editor.dom.isEditable(targetElement);
26826
      }
26827
    };
26828
    const createGhost = (editor, elm, width, height) => {
26829
      const dom = editor.dom;
26830
      const clonedElm = elm.cloneNode(true);
26831
      dom.setStyles(clonedElm, {
26832
        width,
26833
        height
26834
      });
26835
      dom.setAttrib(clonedElm, 'data-mce-selected', null);
26836
      const ghostElm = dom.create('div', {
26837
        'class': 'mce-drag-container',
26838
        'data-mce-bogus': 'all',
26839
        'unselectable': 'on',
26840
        'contenteditable': 'false'
26841
      });
26842
      dom.setStyles(ghostElm, {
26843
        position: 'absolute',
26844
        opacity: 0.5,
26845
        overflow: 'hidden',
26846
        border: 0,
26847
        padding: 0,
26848
        margin: 0,
26849
        width,
26850
        height
26851
      });
26852
      dom.setStyles(clonedElm, {
26853
        margin: 0,
26854
        boxSizing: 'border-box'
26855
      });
26856
      ghostElm.appendChild(clonedElm);
26857
      return ghostElm;
26858
    };
26859
    const appendGhostToBody = (ghostElm, bodyElm) => {
26860
      if (ghostElm.parentNode !== bodyElm) {
26861
        bodyElm.appendChild(ghostElm);
26862
      }
26863
    };
26864
    const scrollEditor = (direction, amount) => win => () => {
26865
      const current = direction === 'left' ? win.scrollX : win.scrollY;
26866
      win.scroll({
26867
        [direction]: current + amount,
26868
        behavior: 'smooth'
26869
      });
26870
    };
26871
    const scrollLeft = scrollEditor('left', -scrollPixelsPerInterval);
26872
    const scrollRight = scrollEditor('left', scrollPixelsPerInterval);
26873
    const scrollUp = scrollEditor('top', -scrollPixelsPerInterval);
26874
    const scrollDown = scrollEditor('top', scrollPixelsPerInterval);
26875
    const moveGhost = (ghostElm, position, width, height, maxX, maxY, mouseY, mouseX, contentAreaContainer, win, state, mouseEventOriginatedFromWithinTheEditor) => {
26876
      let overflowX = 0, overflowY = 0;
26877
      ghostElm.style.left = position.pageX + 'px';
26878
      ghostElm.style.top = position.pageY + 'px';
26879
      if (position.pageX + width > maxX) {
26880
        overflowX = position.pageX + width - maxX;
26881
      }
26882
      if (position.pageY + height > maxY) {
26883
        overflowY = position.pageY + height - maxY;
26884
      }
26885
      ghostElm.style.width = width - overflowX + 'px';
26886
      ghostElm.style.height = height - overflowY + 'px';
26887
      const clientHeight = contentAreaContainer.clientHeight;
26888
      const clientWidth = contentAreaContainer.clientWidth;
26889
      const outerMouseY = mouseY + contentAreaContainer.getBoundingClientRect().top;
26890
      const outerMouseX = mouseX + contentAreaContainer.getBoundingClientRect().left;
26891
      state.on(state => {
26892
        state.intervalId.clear();
26893
        if (state.dragging && mouseEventOriginatedFromWithinTheEditor) {
26894
          if (mouseY + mouseRangeToTriggerScrollInsideEditor >= clientHeight) {
26895
            state.intervalId.set(scrollDown(win));
26896
          } else if (mouseY - mouseRangeToTriggerScrollInsideEditor <= 0) {
26897
            state.intervalId.set(scrollUp(win));
26898
          } else if (mouseX + mouseRangeToTriggerScrollInsideEditor >= clientWidth) {
26899
            state.intervalId.set(scrollRight(win));
26900
          } else if (mouseX - mouseRangeToTriggerScrollInsideEditor <= 0) {
26901
            state.intervalId.set(scrollLeft(win));
26902
          } else if (outerMouseY + mouseRangeToTriggerScrollOutsideEditor >= window.innerHeight) {
26903
            state.intervalId.set(scrollDown(window));
26904
          } else if (outerMouseY - mouseRangeToTriggerScrollOutsideEditor <= 0) {
26905
            state.intervalId.set(scrollUp(window));
26906
          } else if (outerMouseX + mouseRangeToTriggerScrollOutsideEditor >= window.innerWidth) {
26907
            state.intervalId.set(scrollRight(window));
26908
          } else if (outerMouseX - mouseRangeToTriggerScrollOutsideEditor <= 0) {
26909
            state.intervalId.set(scrollLeft(window));
26910
          }
26911
        }
26912
      });
26913
    };
26914
    const removeElement = elm => {
26915
      if (elm && elm.parentNode) {
26916
        elm.parentNode.removeChild(elm);
26917
      }
26918
    };
26919
    const removeElementWithPadding = (dom, elm) => {
26920
      const parentBlock = dom.getParent(elm.parentNode, dom.isBlock);
26921
      removeElement(elm);
26922
      if (parentBlock && parentBlock !== dom.getRoot() && dom.isEmpty(parentBlock)) {
26923
        fillWithPaddingBr(SugarElement.fromDom(parentBlock));
26924
      }
26925
    };
26926
    const isLeftMouseButtonPressed = e => e.button === 0;
26927
    const applyRelPos = (state, position) => ({
26928
      pageX: position.pageX - state.relX,
26929
      pageY: position.pageY + 5
26930
    });
26931
    const start = (state, editor) => e => {
26932
      if (isLeftMouseButtonPressed(e)) {
26933
        const ceElm = find$2(editor.dom.getParents(e.target), isContentEditable).getOr(null);
26934
        if (isNonNullable(ceElm) && isDraggable(editor.dom, editor.getBody(), ceElm)) {
26935
          const elmPos = editor.dom.getPos(ceElm);
26936
          const bodyElm = editor.getBody();
26937
          const docElm = editor.getDoc().documentElement;
26938
          state.set({
26939
            element: ceElm,
26940
            dataTransfer: createDataTransfer(),
26941
            dragging: false,
26942
            screenX: e.screenX,
26943
            screenY: e.screenY,
26944
            maxX: (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2,
26945
            maxY: (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2,
26946
            relX: e.pageX - elmPos.x,
26947
            relY: e.pageY - elmPos.y,
26948
            width: ceElm.offsetWidth,
26949
            height: ceElm.offsetHeight,
26950
            ghost: createGhost(editor, ceElm, ceElm.offsetWidth, ceElm.offsetHeight),
26951
            intervalId: repeatable(scrollIntervalValue)
26952
          });
26953
        }
26954
      }
26955
    };
26956
    const placeCaretAt = (editor, clientX, clientY) => {
26957
      editor._selectionOverrides.hideFakeCaret();
26958
      closestFakeCaretCandidate(editor.getBody(), clientX, clientY).fold(() => editor.selection.placeCaretAt(clientX, clientY), caretInfo => {
26959
        const range = editor._selectionOverrides.showCaret(1, caretInfo.node, caretInfo.position === FakeCaretPosition.Before, false);
26960
        if (range) {
26961
          editor.selection.setRng(range);
26962
        } else {
26963
          editor.selection.placeCaretAt(clientX, clientY);
26964
        }
26965
      });
26966
    };
26967
    const dispatchDragEvent = (editor, type, target, dataTransfer, mouseEvent) => {
26968
      if (type === 'dragstart') {
26969
        setHtmlData(dataTransfer, editor.dom.getOuterHTML(target));
26970
      }
26971
      const event = makeDragEvent(type, target, dataTransfer, mouseEvent);
26972
      const args = editor.dispatch(type, event);
26973
      return args;
26974
    };
26975
    const move = (state, editor) => {
26976
      const throttledPlaceCaretAt = first$1((clientX, clientY) => placeCaretAt(editor, clientX, clientY), 0);
26977
      editor.on('remove', throttledPlaceCaretAt.cancel);
26978
      const state_ = state;
26979
      return e => state.on(state => {
26980
        const movement = Math.max(Math.abs(e.screenX - state.screenX), Math.abs(e.screenY - state.screenY));
26981
        if (!state.dragging && movement > 10) {
26982
          const args = dispatchDragEvent(editor, 'dragstart', state.element, state.dataTransfer, e);
26983
          if (isNonNullable(args.dataTransfer)) {
26984
            state.dataTransfer = args.dataTransfer;
26985
          }
26986
          if (args.isDefaultPrevented()) {
26987
            return;
26988
          }
26989
          state.dragging = true;
26990
          editor.focus();
26991
        }
26992
        if (state.dragging) {
26993
          const mouseEventOriginatedFromWithinTheEditor = e.currentTarget === editor.getDoc().documentElement;
26994
          const targetPos = applyRelPos(state, calc(editor, e));
26995
          appendGhostToBody(state.ghost, editor.getBody());
26996
          moveGhost(state.ghost, targetPos, state.width, state.height, state.maxX, state.maxY, e.clientY, e.clientX, editor.getContentAreaContainer(), editor.getWin(), state_, mouseEventOriginatedFromWithinTheEditor);
26997
          throttledPlaceCaretAt.throttle(e.clientX, e.clientY);
26998
        }
26999
      });
27000
    };
27001
    const getRawTarget = selection => {
27002
      const sel = selection.getSel();
27003
      if (isNonNullable(sel)) {
27004
        const rng = sel.getRangeAt(0);
27005
        const startContainer = rng.startContainer;
27006
        return isText$a(startContainer) ? startContainer.parentNode : startContainer;
27007
      } else {
27008
        return null;
27009
      }
27010
    };
27011
    const drop = (state, editor) => e => {
27012
      state.on(state => {
27013
        var _a;
27014
        state.intervalId.clear();
27015
        if (state.dragging) {
27016
          if (isValidDropTarget(editor, getRawTarget(editor.selection), state.element)) {
27017
            const dropTarget = (_a = editor.getDoc().elementFromPoint(e.clientX, e.clientY)) !== null && _a !== void 0 ? _a : editor.getBody();
27018
            const args = dispatchDragEvent(editor, 'drop', dropTarget, state.dataTransfer, e);
27019
            if (!args.isDefaultPrevented()) {
27020
              editor.undoManager.transact(() => {
27021
                removeElementWithPadding(editor.dom, state.element);
27022
                getHtmlData(state.dataTransfer).each(content => editor.insertContent(content));
27023
                editor._selectionOverrides.hideFakeCaret();
27024
              });
27025
            }
27026
          }
27027
          dispatchDragEvent(editor, 'dragend', editor.getBody(), state.dataTransfer, e);
27028
        }
27029
      });
27030
      removeDragState(state);
27031
    };
27032
    const stopDragging = (state, editor, e) => {
27033
      state.on(state => {
27034
        state.intervalId.clear();
27035
        if (state.dragging) {
27036
          e.fold(() => dispatchDragEvent(editor, 'dragend', state.element, state.dataTransfer), mouseEvent => dispatchDragEvent(editor, 'dragend', state.element, state.dataTransfer, mouseEvent));
27037
        }
27038
      });
27039
      removeDragState(state);
27040
    };
27041
    const stop = (state, editor) => e => stopDragging(state, editor, Optional.some(e));
27042
    const removeDragState = state => {
27043
      state.on(state => {
27044
        state.intervalId.clear();
27045
        removeElement(state.ghost);
27046
      });
27047
      state.clear();
27048
    };
27049
    const bindFakeDragEvents = editor => {
27050
      const state = value$2();
27051
      const pageDom = DOMUtils.DOM;
27052
      const rootDocument = document;
27053
      const dragStartHandler = start(state, editor);
27054
      const dragHandler = move(state, editor);
27055
      const dropHandler = drop(state, editor);
27056
      const dragEndHandler = stop(state, editor);
27057
      editor.on('mousedown', dragStartHandler);
27058
      editor.on('mousemove', dragHandler);
27059
      editor.on('mouseup', dropHandler);
27060
      pageDom.bind(rootDocument, 'mousemove', dragHandler);
27061
      pageDom.bind(rootDocument, 'mouseup', dragEndHandler);
27062
      editor.on('remove', () => {
27063
        pageDom.unbind(rootDocument, 'mousemove', dragHandler);
27064
        pageDom.unbind(rootDocument, 'mouseup', dragEndHandler);
27065
      });
27066
      editor.on('keydown', e => {
27067
        if (e.keyCode === VK.ESC) {
27068
          stopDragging(state, editor, Optional.none());
27069
        }
27070
      });
27071
    };
27072
    const blockUnsupportedFileDrop = editor => {
27073
      const preventFileDrop = e => {
27074
        if (!e.isDefaultPrevented()) {
27075
          const dataTransfer = e.dataTransfer;
27076
          if (dataTransfer && (contains$2(dataTransfer.types, 'Files') || dataTransfer.files.length > 0)) {
27077
            e.preventDefault();
27078
            if (e.type === 'drop') {
27079
              displayError(editor, 'Dropped file type is not supported');
27080
            }
27081
          }
27082
        }
27083
      };
27084
      const preventFileDropIfUIElement = e => {
27085
        if (isUIElement(editor, e.target)) {
27086
          preventFileDrop(e);
27087
        }
27088
      };
27089
      const setup = () => {
27090
        const pageDom = DOMUtils.DOM;
27091
        const dom = editor.dom;
27092
        const doc = document;
27093
        const editorRoot = editor.inline ? editor.getBody() : editor.getDoc();
27094
        const eventNames = [
27095
          'drop',
27096
          'dragover'
27097
        ];
27098
        each$e(eventNames, name => {
27099
          pageDom.bind(doc, name, preventFileDropIfUIElement);
27100
          dom.bind(editorRoot, name, preventFileDrop);
27101
        });
27102
        editor.on('remove', () => {
27103
          each$e(eventNames, name => {
27104
            pageDom.unbind(doc, name, preventFileDropIfUIElement);
27105
            dom.unbind(editorRoot, name, preventFileDrop);
27106
          });
27107
        });
27108
      };
27109
      editor.on('init', () => {
27110
        Delay.setEditorTimeout(editor, setup, 0);
27111
      });
27112
    };
27113
    const init$2 = editor => {
27114
      bindFakeDragEvents(editor);
27115
      if (shouldBlockUnsupportedDrop(editor)) {
27116
        blockUnsupportedFileDrop(editor);
27117
      }
27118
    };
27119
 
27120
    const setup$4 = editor => {
27121
      const renderFocusCaret = first$1(() => {
27122
        if (!editor.removed && editor.getBody().contains(document.activeElement)) {
27123
          const rng = editor.selection.getRng();
27124
          if (rng.collapsed) {
27125
            const caretRange = renderRangeCaret(editor, rng, false);
27126
            editor.selection.setRng(caretRange);
27127
          }
27128
        }
27129
      }, 0);
27130
      editor.on('focus', () => {
27131
        renderFocusCaret.throttle();
27132
      });
27133
      editor.on('blur', () => {
27134
        renderFocusCaret.cancel();
27135
      });
27136
    };
27137
 
27138
    const setup$3 = editor => {
27139
      editor.on('init', () => {
27140
        editor.on('focusin', e => {
27141
          const target = e.target;
27142
          if (isMedia$2(target)) {
27143
            const ceRoot = getContentEditableRoot$1(editor.getBody(), target);
27144
            const node = isContentEditableFalse$b(ceRoot) ? ceRoot : target;
27145
            if (editor.selection.getNode() !== node) {
27146
              selectNode(editor, node).each(rng => editor.selection.setRng(rng));
27147
            }
27148
          }
27149
        });
27150
      });
27151
    };
27152
 
27153
    const isContentEditableFalse = isContentEditableFalse$b;
27154
    const getContentEditableRoot = (editor, node) => getContentEditableRoot$1(editor.getBody(), node);
27155
    const SelectionOverrides = editor => {
27156
      const selection = editor.selection, dom = editor.dom;
27157
      const rootNode = editor.getBody();
27158
      const fakeCaret = FakeCaret(editor, rootNode, dom.isBlock, () => hasFocus(editor));
27159
      const realSelectionId = 'sel-' + dom.uniqueId();
27160
      const elementSelectionAttr = 'data-mce-selected';
27161
      let selectedElement;
27162
      const isFakeSelectionElement = node => isNonNullable(node) && dom.hasClass(node, 'mce-offscreen-selection');
27163
      const isFakeSelectionTargetElement = node => node !== rootNode && (isContentEditableFalse(node) || isMedia$2(node)) && dom.isChildOf(node, rootNode) && dom.isEditable(node.parentNode);
27164
      const setRange = range => {
27165
        if (range) {
27166
          selection.setRng(range);
27167
        }
27168
      };
27169
      const showCaret = (direction, node, before, scrollIntoView = true) => {
27170
        const e = editor.dispatch('ShowCaret', {
27171
          target: node,
27172
          direction,
27173
          before
27174
        });
27175
        if (e.isDefaultPrevented()) {
27176
          return null;
27177
        }
27178
        if (scrollIntoView) {
27179
          selection.scrollIntoView(node, direction === -1);
27180
        }
27181
        return fakeCaret.show(before, node);
27182
      };
27183
      const showBlockCaretContainer = blockCaretContainer => {
27184
        if (blockCaretContainer.hasAttribute('data-mce-caret')) {
27185
          showCaretContainerBlock(blockCaretContainer);
27186
          selection.scrollIntoView(blockCaretContainer);
27187
        }
27188
      };
27189
      const registerEvents = () => {
27190
        editor.on('click', e => {
27191
          if (!dom.isEditable(e.target)) {
27192
            e.preventDefault();
27193
            editor.focus();
27194
          }
27195
        });
27196
        editor.on('blur NewBlock', removeElementSelection);
27197
        editor.on('ResizeWindow FullscreenStateChanged', fakeCaret.reposition);
27198
        editor.on('tap', e => {
27199
          const targetElm = e.target;
27200
          const contentEditableRoot = getContentEditableRoot(editor, targetElm);
27201
          if (isContentEditableFalse(contentEditableRoot)) {
27202
            e.preventDefault();
27203
            selectNode(editor, contentEditableRoot).each(setElementSelection);
27204
          } else if (isFakeSelectionTargetElement(targetElm)) {
27205
            selectNode(editor, targetElm).each(setElementSelection);
27206
          }
27207
        }, true);
27208
        editor.on('mousedown', e => {
27209
          const targetElm = e.target;
27210
          if (targetElm !== rootNode && targetElm.nodeName !== 'HTML' && !dom.isChildOf(targetElm, rootNode)) {
27211
            return;
27212
          }
27213
          if (!isXYInContentArea(editor, e.clientX, e.clientY)) {
27214
            return;
27215
          }
27216
          removeElementSelection();
27217
          hideFakeCaret();
27218
          const closestContentEditable = getContentEditableRoot(editor, targetElm);
27219
          if (isContentEditableFalse(closestContentEditable)) {
27220
            e.preventDefault();
27221
            selectNode(editor, closestContentEditable).each(setElementSelection);
27222
          } else {
27223
            closestFakeCaretCandidate(rootNode, e.clientX, e.clientY).each(caretInfo => {
27224
              e.preventDefault();
27225
              const range = showCaret(1, caretInfo.node, caretInfo.position === FakeCaretPosition.Before, false);
27226
              setRange(range);
27227
              if (isHTMLElement(closestContentEditable)) {
27228
                closestContentEditable.focus();
27229
              } else {
27230
                editor.getBody().focus();
27231
              }
27232
            });
27233
          }
27234
        });
27235
        editor.on('keypress', e => {
27236
          if (VK.modifierPressed(e)) {
27237
            return;
27238
          }
27239
          if (isContentEditableFalse(selection.getNode())) {
27240
            e.preventDefault();
27241
          }
27242
        });
27243
        editor.on('GetSelectionRange', e => {
27244
          let rng = e.range;
27245
          if (selectedElement) {
27246
            if (!selectedElement.parentNode) {
27247
              selectedElement = null;
27248
              return;
27249
            }
27250
            rng = rng.cloneRange();
27251
            rng.selectNode(selectedElement);
27252
            e.range = rng;
27253
          }
27254
        });
27255
        editor.on('SetSelectionRange', e => {
27256
          e.range = normalizeVoidElementSelection(e.range);
27257
          const rng = setElementSelection(e.range, e.forward);
27258
          if (rng) {
27259
            e.range = rng;
27260
          }
27261
        });
27262
        const isPasteBin = node => isElement$6(node) && node.id === 'mcepastebin';
27263
        editor.on('AfterSetSelectionRange', e => {
27264
          const rng = e.range;
27265
          const parent = rng.startContainer.parentElement;
27266
          if (!isRangeInCaretContainer(rng) && !isPasteBin(parent)) {
27267
            hideFakeCaret();
27268
          }
27269
          if (!isFakeSelectionElement(parent)) {
27270
            removeElementSelection();
27271
          }
27272
        });
27273
        init$2(editor);
27274
        setup$4(editor);
27275
        setup$3(editor);
27276
      };
27277
      const isWithinCaretContainer = node => isCaretContainer$2(node) || startsWithCaretContainer$1(node) || endsWithCaretContainer$1(node);
27278
      const isRangeInCaretContainer = rng => isWithinCaretContainer(rng.startContainer) || isWithinCaretContainer(rng.endContainer);
27279
      const normalizeVoidElementSelection = rng => {
27280
        const voidElements = editor.schema.getVoidElements();
27281
        const newRng = dom.createRng();
27282
        const startContainer = rng.startContainer;
27283
        const startOffset = rng.startOffset;
27284
        const endContainer = rng.endContainer;
27285
        const endOffset = rng.endOffset;
27286
        if (has$2(voidElements, startContainer.nodeName.toLowerCase())) {
27287
          if (startOffset === 0) {
27288
            newRng.setStartBefore(startContainer);
27289
          } else {
27290
            newRng.setStartAfter(startContainer);
27291
          }
27292
        } else {
27293
          newRng.setStart(startContainer, startOffset);
27294
        }
27295
        if (has$2(voidElements, endContainer.nodeName.toLowerCase())) {
27296
          if (endOffset === 0) {
27297
            newRng.setEndBefore(endContainer);
27298
          } else {
27299
            newRng.setEndAfter(endContainer);
27300
          }
27301
        } else {
27302
          newRng.setEnd(endContainer, endOffset);
27303
        }
27304
        return newRng;
27305
      };
27306
      const setupOffscreenSelection = (node, targetClone) => {
27307
        const body = SugarElement.fromDom(editor.getBody());
27308
        const doc = editor.getDoc();
27309
        const realSelectionContainer = descendant$1(body, '#' + realSelectionId).getOrThunk(() => {
27310
          const newContainer = SugarElement.fromHtml('<div data-mce-bogus="all" class="mce-offscreen-selection"></div>', doc);
27311
          set$3(newContainer, 'id', realSelectionId);
27312
          append$1(body, newContainer);
27313
          return newContainer;
27314
        });
27315
        const newRange = dom.createRng();
27316
        empty(realSelectionContainer);
27317
        append(realSelectionContainer, [
27318
          SugarElement.fromText(nbsp, doc),
27319
          SugarElement.fromDom(targetClone),
27320
          SugarElement.fromText(nbsp, doc)
27321
        ]);
27322
        newRange.setStart(realSelectionContainer.dom.firstChild, 1);
27323
        newRange.setEnd(realSelectionContainer.dom.lastChild, 0);
27324
        setAll(realSelectionContainer, { top: dom.getPos(node, editor.getBody()).y + 'px' });
27325
        focus$1(realSelectionContainer);
27326
        const sel = selection.getSel();
27327
        if (sel) {
27328
          sel.removeAllRanges();
27329
          sel.addRange(newRange);
27330
        }
27331
        return newRange;
27332
      };
27333
      const selectElement = elm => {
27334
        const targetClone = elm.cloneNode(true);
27335
        const e = editor.dispatch('ObjectSelected', {
27336
          target: elm,
27337
          targetClone
27338
        });
27339
        if (e.isDefaultPrevented()) {
27340
          return null;
27341
        }
27342
        const range = setupOffscreenSelection(elm, e.targetClone);
27343
        const nodeElm = SugarElement.fromDom(elm);
27344
        each$e(descendants(SugarElement.fromDom(editor.getBody()), `*[${ elementSelectionAttr }]`), elm => {
27345
          if (!eq(nodeElm, elm)) {
27346
            remove$a(elm, elementSelectionAttr);
27347
          }
27348
        });
27349
        if (!dom.getAttrib(elm, elementSelectionAttr)) {
27350
          elm.setAttribute(elementSelectionAttr, '1');
27351
        }
27352
        selectedElement = elm;
27353
        hideFakeCaret();
27354
        return range;
27355
      };
27356
      const setElementSelection = (range, forward) => {
27357
        if (!range) {
27358
          return null;
27359
        }
27360
        if (range.collapsed) {
27361
          if (!isRangeInCaretContainer(range)) {
27362
            const dir = forward ? 1 : -1;
27363
            const caretPosition = getNormalizedRangeEndPoint(dir, rootNode, range);
27364
            const beforeNode = caretPosition.getNode(!forward);
27365
            if (isNonNullable(beforeNode)) {
27366
              if (isFakeCaretTarget(beforeNode)) {
27367
                return showCaret(dir, beforeNode, forward ? !caretPosition.isAtEnd() : false, false);
27368
              }
27369
              if (isCaretContainerInline(beforeNode) && isContentEditableFalse$b(beforeNode.nextSibling)) {
27370
                const rng = dom.createRng();
27371
                rng.setStart(beforeNode, 0);
27372
                rng.setEnd(beforeNode, 0);
27373
                return rng;
27374
              }
27375
            }
27376
            const afterNode = caretPosition.getNode(forward);
27377
            if (isNonNullable(afterNode)) {
27378
              if (isFakeCaretTarget(afterNode)) {
27379
                return showCaret(dir, afterNode, forward ? false : !caretPosition.isAtEnd(), false);
27380
              }
27381
              if (isCaretContainerInline(afterNode) && isContentEditableFalse$b(afterNode.previousSibling)) {
27382
                const rng = dom.createRng();
27383
                rng.setStart(afterNode, 1);
27384
                rng.setEnd(afterNode, 1);
27385
                return rng;
27386
              }
27387
            }
27388
          }
27389
          return null;
27390
        }
27391
        let startContainer = range.startContainer;
27392
        let startOffset = range.startOffset;
27393
        const endOffset = range.endOffset;
27394
        if (isText$a(startContainer) && startOffset === 0 && isContentEditableFalse(startContainer.parentNode)) {
27395
          startContainer = startContainer.parentNode;
27396
          startOffset = dom.nodeIndex(startContainer);
27397
          startContainer = startContainer.parentNode;
27398
        }
27399
        if (!isElement$6(startContainer)) {
27400
          return null;
27401
        }
27402
        if (endOffset === startOffset + 1 && startContainer === range.endContainer) {
27403
          const node = startContainer.childNodes[startOffset];
27404
          if (isFakeSelectionTargetElement(node)) {
27405
            return selectElement(node);
27406
          }
27407
        }
27408
        return null;
27409
      };
27410
      const removeElementSelection = () => {
27411
        if (selectedElement) {
27412
          selectedElement.removeAttribute(elementSelectionAttr);
27413
        }
27414
        descendant$1(SugarElement.fromDom(editor.getBody()), '#' + realSelectionId).each(remove$5);
27415
        selectedElement = null;
27416
      };
27417
      const destroy = () => {
27418
        fakeCaret.destroy();
27419
        selectedElement = null;
27420
      };
27421
      const hideFakeCaret = () => {
27422
        fakeCaret.hide();
27423
      };
27424
      if (!isRtc(editor)) {
27425
        registerEvents();
27426
      }
27427
      return {
27428
        showCaret,
27429
        showBlockCaretContainer,
27430
        hideFakeCaret,
27431
        destroy
27432
      };
27433
    };
27434
 
27435
    const getNormalizedTextOffset = (container, offset) => {
27436
      let normalizedOffset = offset;
27437
      for (let node = container.previousSibling; isText$a(node); node = node.previousSibling) {
27438
        normalizedOffset += node.data.length;
27439
      }
27440
      return normalizedOffset;
27441
    };
27442
    const generatePath = (dom, root, node, offset, normalized) => {
27443
      if (isText$a(node) && (offset < 0 || offset > node.data.length)) {
27444
        return [];
27445
      }
27446
      const p = normalized && isText$a(node) ? [getNormalizedTextOffset(node, offset)] : [offset];
27447
      let current = node;
27448
      while (current !== root && current.parentNode) {
27449
        p.push(dom.nodeIndex(current, normalized));
27450
        current = current.parentNode;
27451
      }
27452
      return current === root ? p.reverse() : [];
27453
    };
27454
    const generatePathRange = (dom, root, startNode, startOffset, endNode, endOffset, normalized = false) => {
27455
      const start = generatePath(dom, root, startNode, startOffset, normalized);
27456
      const end = generatePath(dom, root, endNode, endOffset, normalized);
27457
      return {
27458
        start,
27459
        end
27460
      };
27461
    };
27462
    const resolvePath = (root, path) => {
27463
      const nodePath = path.slice();
27464
      const offset = nodePath.pop();
27465
      if (!isNumber(offset)) {
27466
        return Optional.none();
27467
      } else {
27468
        const resolvedNode = foldl(nodePath, (optNode, index) => optNode.bind(node => Optional.from(node.childNodes[index])), Optional.some(root));
27469
        return resolvedNode.bind(node => {
27470
          if (isText$a(node) && (offset < 0 || offset > node.data.length)) {
27471
            return Optional.none();
27472
          } else {
27473
            return Optional.some({
27474
              node,
27475
              offset
27476
            });
27477
          }
27478
        });
27479
      }
27480
    };
27481
    const resolvePathRange = (root, range) => resolvePath(root, range.start).bind(({
27482
      node: startNode,
27483
      offset: startOffset
27484
    }) => resolvePath(root, range.end).map(({
27485
      node: endNode,
27486
      offset: endOffset
27487
    }) => {
27488
      const rng = document.createRange();
27489
      rng.setStart(startNode, startOffset);
27490
      rng.setEnd(endNode, endOffset);
27491
      return rng;
27492
    }));
27493
    const generatePathRangeFromRange = (dom, root, range, normalized = false) => generatePathRange(dom, root, range.startContainer, range.startOffset, range.endContainer, range.endOffset, normalized);
27494
 
27495
    const cleanEmptyNodes = (dom, node, isRoot) => {
27496
      if (node && dom.isEmpty(node) && !isRoot(node)) {
27497
        const parent = node.parentNode;
27498
        dom.remove(node, isText$a(node.firstChild) && isWhitespaceText(node.firstChild.data));
27499
        cleanEmptyNodes(dom, parent, isRoot);
27500
      }
27501
    };
27502
    const deleteRng = (dom, rng, isRoot, clean = true) => {
27503
      const startParent = rng.startContainer.parentNode;
27504
      const endParent = rng.endContainer.parentNode;
27505
      rng.deleteContents();
27506
      if (clean && !isRoot(rng.startContainer)) {
27507
        if (isText$a(rng.startContainer) && rng.startContainer.data.length === 0) {
27508
          dom.remove(rng.startContainer);
27509
        }
27510
        if (isText$a(rng.endContainer) && rng.endContainer.data.length === 0) {
27511
          dom.remove(rng.endContainer);
27512
        }
27513
        cleanEmptyNodes(dom, startParent, isRoot);
27514
        if (startParent !== endParent) {
27515
          cleanEmptyNodes(dom, endParent, isRoot);
27516
        }
27517
      }
27518
    };
27519
    const getParentBlock = (editor, rng) => Optional.from(editor.dom.getParent(rng.startContainer, editor.dom.isBlock));
27520
    const resolveFromDynamicPatterns = (patternSet, block, beforeText) => {
27521
      const dynamicPatterns = patternSet.dynamicPatternsLookup({
27522
        text: beforeText,
27523
        block
27524
      });
27525
      return {
27526
        ...patternSet,
27527
        blockPatterns: getBlockPatterns(dynamicPatterns).concat(patternSet.blockPatterns),
27528
        inlinePatterns: getInlinePatterns(dynamicPatterns).concat(patternSet.inlinePatterns)
27529
      };
27530
    };
27531
    const getBeforeText = (dom, block, node, offset) => {
27532
      const rng = dom.createRng();
27533
      rng.setStart(block, 0);
27534
      rng.setEnd(node, offset);
27535
      return rng.toString();
27536
    };
27537
 
27538
    const startsWithSingleSpace = s => /^\s[^\s]/.test(s);
27539
    const stripPattern = (dom, block, pattern) => {
27540
      const firstTextNode = textAfter(block, 0, block);
27541
      firstTextNode.each(spot => {
27542
        const node = spot.container;
27543
        scanRight(node, pattern.start.length, block).each(end => {
27544
          const rng = dom.createRng();
27545
          rng.setStart(node, 0);
27546
          rng.setEnd(end.container, end.offset);
27547
          deleteRng(dom, rng, e => e === block);
27548
        });
27549
        const text = SugarElement.fromDom(node);
27550
        const textContent = get$3(text);
27551
        if (startsWithSingleSpace(textContent)) {
27552
          set(text, textContent.slice(1));
27553
        }
27554
      });
27555
    };
27556
    const applyPattern$1 = (editor, match) => {
27557
      const dom = editor.dom;
27558
      const pattern = match.pattern;
27559
      const rng = resolvePathRange(dom.getRoot(), match.range).getOrDie('Unable to resolve path range');
27560
      const isBlockFormatName = (name, formatter) => {
27561
        const formatSet = formatter.get(name);
27562
        return isArray$1(formatSet) && head(formatSet).exists(format => has$2(format, 'block'));
27563
      };
27564
      getParentBlock(editor, rng).each(block => {
27565
        if (pattern.type === 'block-format') {
27566
          if (isBlockFormatName(pattern.format, editor.formatter)) {
27567
            editor.undoManager.transact(() => {
27568
              stripPattern(editor.dom, block, pattern);
27569
              editor.formatter.apply(pattern.format);
27570
            });
27571
          }
27572
        } else if (pattern.type === 'block-command') {
27573
          editor.undoManager.transact(() => {
27574
            stripPattern(editor.dom, block, pattern);
27575
            editor.execCommand(pattern.cmd, false, pattern.value);
27576
          });
27577
        }
27578
      });
27579
      return true;
27580
    };
27581
    const sortPatterns$1 = patterns => sort(patterns, (a, b) => b.start.length - a.start.length);
27582
    const findPattern$1 = (patterns, text) => {
27583
      const sortedPatterns = sortPatterns$1(patterns);
27584
      const nuText = text.replace(nbsp, ' ');
27585
      return find$2(sortedPatterns, pattern => text.indexOf(pattern.start) === 0 || nuText.indexOf(pattern.start) === 0);
27586
    };
27587
    const findPatterns$1 = (editor, block, patternSet, normalizedMatches) => {
27588
      var _a;
27589
      const dom = editor.dom;
27590
      const forcedRootBlock = getForcedRootBlock(editor);
27591
      if (!dom.is(block, forcedRootBlock)) {
27592
        return [];
27593
      }
27594
      const blockText = (_a = block.textContent) !== null && _a !== void 0 ? _a : '';
27595
      return findPattern$1(patternSet.blockPatterns, blockText).map(pattern => {
27596
        if (Tools.trim(blockText).length === pattern.start.length) {
27597
          return [];
27598
        }
27599
        return [{
27600
            pattern,
27601
            range: generatePathRange(dom, dom.getRoot(), block, 0, block, 0, normalizedMatches)
27602
          }];
27603
      }).getOr([]);
27604
    };
27605
    const applyMatches$1 = (editor, matches) => {
27606
      if (matches.length === 0) {
27607
        return;
27608
      }
27609
      const bookmark = editor.selection.getBookmark();
27610
      each$e(matches, match => applyPattern$1(editor, match));
27611
      editor.selection.moveToBookmark(bookmark);
27612
    };
27613
 
27614
    const newMarker = (dom, id) => dom.create('span', {
27615
      'data-mce-type': 'bookmark',
27616
      id
27617
    });
27618
    const rangeFromMarker = (dom, marker) => {
27619
      const rng = dom.createRng();
27620
      rng.setStartAfter(marker.start);
27621
      rng.setEndBefore(marker.end);
27622
      return rng;
27623
    };
27624
    const createMarker = (dom, markerPrefix, pathRange) => {
27625
      const rng = resolvePathRange(dom.getRoot(), pathRange).getOrDie('Unable to resolve path range');
27626
      const startNode = rng.startContainer;
27627
      const endNode = rng.endContainer;
27628
      const textEnd = rng.endOffset === 0 ? endNode : endNode.splitText(rng.endOffset);
27629
      const textStart = rng.startOffset === 0 ? startNode : startNode.splitText(rng.startOffset);
27630
      const startParentNode = textStart.parentNode;
27631
      const endParentNode = textEnd.parentNode;
27632
      return {
27633
        prefix: markerPrefix,
27634
        end: endParentNode.insertBefore(newMarker(dom, markerPrefix + '-end'), textEnd),
27635
        start: startParentNode.insertBefore(newMarker(dom, markerPrefix + '-start'), textStart)
27636
      };
27637
    };
27638
    const removeMarker = (dom, marker, isRoot) => {
27639
      cleanEmptyNodes(dom, dom.get(marker.prefix + '-end'), isRoot);
27640
      cleanEmptyNodes(dom, dom.get(marker.prefix + '-start'), isRoot);
27641
    };
27642
 
27643
    const isReplacementPattern = pattern => pattern.start.length === 0;
27644
    const matchesPattern = patternContent => (element, offset) => {
27645
      const text = element.data;
27646
      const searchText = text.substring(0, offset);
27647
      const startEndIndex = searchText.lastIndexOf(patternContent.charAt(patternContent.length - 1));
27648
      const startIndex = searchText.lastIndexOf(patternContent);
27649
      if (startIndex !== -1) {
27650
        return startIndex + patternContent.length;
27651
      } else if (startEndIndex !== -1) {
27652
        return startEndIndex + 1;
27653
      } else {
27654
        return -1;
27655
      }
27656
    };
27657
    const findPatternStartFromSpot = (dom, pattern, block, spot) => {
27658
      const startPattern = pattern.start;
27659
      const startSpot = repeatLeft(dom, spot.container, spot.offset, matchesPattern(startPattern), block);
27660
      return startSpot.bind(spot => {
27661
        var _a, _b;
27662
        const startPatternIndex = (_b = (_a = block.textContent) === null || _a === void 0 ? void 0 : _a.indexOf(startPattern)) !== null && _b !== void 0 ? _b : -1;
27663
        const isCompleteMatch = startPatternIndex !== -1 && spot.offset >= startPatternIndex + startPattern.length;
27664
        if (isCompleteMatch) {
27665
          const rng = dom.createRng();
27666
          rng.setStart(spot.container, spot.offset - startPattern.length);
27667
          rng.setEnd(spot.container, spot.offset);
27668
          return Optional.some(rng);
27669
        } else {
27670
          const offset = spot.offset - startPattern.length;
27671
          return scanLeft(spot.container, offset, block).map(nextSpot => {
27672
            const rng = dom.createRng();
27673
            rng.setStart(nextSpot.container, nextSpot.offset);
27674
            rng.setEnd(spot.container, spot.offset);
27675
            return rng;
27676
          }).filter(rng => rng.toString() === startPattern).orThunk(() => findPatternStartFromSpot(dom, pattern, block, point(spot.container, 0)));
27677
        }
27678
      });
27679
    };
27680
    const findPatternStart = (dom, pattern, node, offset, block, requireGap = false) => {
27681
      if (pattern.start.length === 0 && !requireGap) {
27682
        const rng = dom.createRng();
27683
        rng.setStart(node, offset);
27684
        rng.setEnd(node, offset);
27685
        return Optional.some(rng);
27686
      }
27687
      return textBefore(node, offset, block).bind(spot => {
27688
        const start = findPatternStartFromSpot(dom, pattern, block, spot);
27689
        return start.bind(startRange => {
27690
          var _a;
27691
          if (requireGap) {
27692
            if (startRange.endContainer === spot.container && startRange.endOffset === spot.offset) {
27693
              return Optional.none();
27694
            } else if (spot.offset === 0 && ((_a = startRange.endContainer.textContent) === null || _a === void 0 ? void 0 : _a.length) === startRange.endOffset) {
27695
              return Optional.none();
27696
            }
27697
          }
27698
          return Optional.some(startRange);
27699
        });
27700
      });
27701
    };
27702
    const findPattern = (editor, block, details, normalizedMatches) => {
27703
      const dom = editor.dom;
27704
      const root = dom.getRoot();
27705
      const pattern = details.pattern;
27706
      const endNode = details.position.container;
27707
      const endOffset = details.position.offset;
27708
      return scanLeft(endNode, endOffset - details.pattern.end.length, block).bind(spot => {
27709
        const endPathRng = generatePathRange(dom, root, spot.container, spot.offset, endNode, endOffset, normalizedMatches);
27710
        if (isReplacementPattern(pattern)) {
27711
          return Optional.some({
27712
            matches: [{
27713
                pattern,
27714
                startRng: endPathRng,
27715
                endRng: endPathRng
27716
              }],
27717
            position: spot
27718
          });
27719
        } else {
27720
          const resultsOpt = findPatternsRec(editor, details.remainingPatterns, spot.container, spot.offset, block, normalizedMatches);
27721
          const results = resultsOpt.getOr({
27722
            matches: [],
27723
            position: spot
27724
          });
27725
          const pos = results.position;
27726
          const start = findPatternStart(dom, pattern, pos.container, pos.offset, block, resultsOpt.isNone());
27727
          return start.map(startRng => {
27728
            const startPathRng = generatePathRangeFromRange(dom, root, startRng, normalizedMatches);
27729
            return {
27730
              matches: results.matches.concat([{
27731
                  pattern,
27732
                  startRng: startPathRng,
27733
                  endRng: endPathRng
27734
                }]),
27735
              position: point(startRng.startContainer, startRng.startOffset)
27736
            };
27737
          });
27738
        }
27739
      });
27740
    };
27741
    const findPatternsRec = (editor, patterns, node, offset, block, normalizedMatches) => {
27742
      const dom = editor.dom;
27743
      return textBefore(node, offset, dom.getRoot()).bind(endSpot => {
27744
        const text = getBeforeText(dom, block, node, offset);
27745
        for (let i = 0; i < patterns.length; i++) {
27746
          const pattern = patterns[i];
27747
          if (!endsWith(text, pattern.end)) {
27748
            continue;
27749
          }
27750
          const patternsWithoutCurrent = patterns.slice();
27751
          patternsWithoutCurrent.splice(i, 1);
27752
          const result = findPattern(editor, block, {
27753
            pattern,
27754
            remainingPatterns: patternsWithoutCurrent,
27755
            position: endSpot
27756
          }, normalizedMatches);
27757
          if (result.isNone() && offset > 0) {
27758
            return findPatternsRec(editor, patterns, node, offset - 1, block, normalizedMatches);
27759
          }
27760
          if (result.isSome()) {
27761
            return result;
27762
          }
27763
        }
27764
        return Optional.none();
27765
      });
27766
    };
27767
    const applyPattern = (editor, pattern, patternRange) => {
27768
      editor.selection.setRng(patternRange);
27769
      if (pattern.type === 'inline-format') {
27770
        each$e(pattern.format, format => {
27771
          editor.formatter.apply(format);
27772
        });
27773
      } else {
27774
        editor.execCommand(pattern.cmd, false, pattern.value);
27775
      }
27776
    };
27777
    const applyReplacementPattern = (editor, pattern, marker, isRoot) => {
27778
      const markerRange = rangeFromMarker(editor.dom, marker);
27779
      deleteRng(editor.dom, markerRange, isRoot);
27780
      applyPattern(editor, pattern, markerRange);
27781
    };
27782
    const applyPatternWithContent = (editor, pattern, startMarker, endMarker, isRoot) => {
27783
      const dom = editor.dom;
27784
      const markerEndRange = rangeFromMarker(dom, endMarker);
27785
      const markerStartRange = rangeFromMarker(dom, startMarker);
27786
      deleteRng(dom, markerStartRange, isRoot);
27787
      deleteRng(dom, markerEndRange, isRoot);
27788
      const patternMarker = {
27789
        prefix: startMarker.prefix,
27790
        start: startMarker.end,
27791
        end: endMarker.start
27792
      };
27793
      const patternRange = rangeFromMarker(dom, patternMarker);
27794
      applyPattern(editor, pattern, patternRange);
27795
    };
27796
    const addMarkers = (dom, matches) => {
27797
      const markerPrefix = generate$1('mce_textpattern');
27798
      const matchesWithEnds = foldr(matches, (acc, match) => {
27799
        const endMarker = createMarker(dom, markerPrefix + `_end${ acc.length }`, match.endRng);
27800
        return acc.concat([{
27801
            ...match,
27802
            endMarker
27803
          }]);
27804
      }, []);
27805
      return foldr(matchesWithEnds, (acc, match) => {
27806
        const idx = matchesWithEnds.length - acc.length - 1;
27807
        const startMarker = isReplacementPattern(match.pattern) ? match.endMarker : createMarker(dom, markerPrefix + `_start${ idx }`, match.startRng);
27808
        return acc.concat([{
27809
            ...match,
27810
            startMarker
27811
          }]);
27812
      }, []);
27813
    };
27814
    const sortPatterns = patterns => sort(patterns, (a, b) => b.end.length - a.end.length);
27815
    const getBestMatches = (matches, matchesWithSortedPatterns) => {
27816
      const hasSameMatches = forall(matches, match => exists(matchesWithSortedPatterns, sortedMatch => match.pattern.start === sortedMatch.pattern.start && match.pattern.end === sortedMatch.pattern.end));
27817
      if (matches.length === matchesWithSortedPatterns.length) {
27818
        if (hasSameMatches) {
27819
          return matches;
27820
        } else {
27821
          return matchesWithSortedPatterns;
27822
        }
27823
      }
27824
      return matches.length > matchesWithSortedPatterns.length ? matches : matchesWithSortedPatterns;
27825
    };
27826
    const findPatterns = (editor, block, node, offset, patternSet, normalizedMatches) => {
27827
      const matches = findPatternsRec(editor, patternSet.inlinePatterns, node, offset, block, normalizedMatches).fold(() => [], result => result.matches);
27828
      const matchesWithSortedPatterns = findPatternsRec(editor, sortPatterns(patternSet.inlinePatterns), node, offset, block, normalizedMatches).fold(() => [], result => result.matches);
27829
      return getBestMatches(matches, matchesWithSortedPatterns);
27830
    };
27831
    const applyMatches = (editor, matches) => {
27832
      if (matches.length === 0) {
27833
        return;
27834
      }
27835
      const dom = editor.dom;
27836
      const bookmark = editor.selection.getBookmark();
27837
      const matchesWithMarkers = addMarkers(dom, matches);
27838
      each$e(matchesWithMarkers, match => {
27839
        const block = dom.getParent(match.startMarker.start, dom.isBlock);
27840
        const isRoot = node => node === block;
27841
        if (isReplacementPattern(match.pattern)) {
27842
          applyReplacementPattern(editor, match.pattern, match.endMarker, isRoot);
27843
        } else {
27844
          applyPatternWithContent(editor, match.pattern, match.startMarker, match.endMarker, isRoot);
27845
        }
27846
        removeMarker(dom, match.endMarker, isRoot);
27847
        removeMarker(dom, match.startMarker, isRoot);
27848
      });
27849
      editor.selection.moveToBookmark(bookmark);
27850
    };
27851
 
27852
    const handleEnter = (editor, patternSet) => {
27853
      const rng = editor.selection.getRng();
27854
      return getParentBlock(editor, rng).map(block => {
27855
        var _a;
27856
        const offset = Math.max(0, rng.startOffset);
27857
        const dynamicPatternSet = resolveFromDynamicPatterns(patternSet, block, (_a = block.textContent) !== null && _a !== void 0 ? _a : '');
27858
        const inlineMatches = findPatterns(editor, block, rng.startContainer, offset, dynamicPatternSet, true);
27859
        const blockMatches = findPatterns$1(editor, block, dynamicPatternSet, true);
27860
        if (blockMatches.length > 0 || inlineMatches.length > 0) {
27861
          editor.undoManager.add();
27862
          editor.undoManager.extra(() => {
27863
            editor.execCommand('mceInsertNewLine');
27864
          }, () => {
27865
            insert$5(editor);
27866
            applyMatches(editor, inlineMatches);
27867
            applyMatches$1(editor, blockMatches);
27868
            const range = editor.selection.getRng();
27869
            const spot = textBefore(range.startContainer, range.startOffset, editor.dom.getRoot());
27870
            editor.execCommand('mceInsertNewLine');
27871
            spot.each(s => {
27872
              const node = s.container;
27873
              if (node.data.charAt(s.offset - 1) === zeroWidth) {
27874
                node.deleteData(s.offset - 1, 1);
27875
                cleanEmptyNodes(editor.dom, node.parentNode, e => e === editor.dom.getRoot());
27876
              }
27877
            });
27878
          });
27879
          return true;
27880
        }
27881
        return false;
27882
      }).getOr(false);
27883
    };
27884
    const handleInlineKey = (editor, patternSet) => {
27885
      const rng = editor.selection.getRng();
27886
      getParentBlock(editor, rng).map(block => {
27887
        const offset = Math.max(0, rng.startOffset - 1);
27888
        const beforeText = getBeforeText(editor.dom, block, rng.startContainer, offset);
27889
        const dynamicPatternSet = resolveFromDynamicPatterns(patternSet, block, beforeText);
27890
        const inlineMatches = findPatterns(editor, block, rng.startContainer, offset, dynamicPatternSet, false);
27891
        if (inlineMatches.length > 0) {
27892
          editor.undoManager.transact(() => {
27893
            applyMatches(editor, inlineMatches);
27894
          });
27895
        }
27896
      });
27897
    };
27898
    const checkKeyEvent = (codes, event, predicate) => {
27899
      for (let i = 0; i < codes.length; i++) {
27900
        if (predicate(codes[i], event)) {
27901
          return true;
27902
        }
27903
      }
27904
      return false;
27905
    };
27906
    const checkKeyCode = (codes, event) => checkKeyEvent(codes, event, (code, event) => {
27907
      return code === event.keyCode && !VK.modifierPressed(event);
27908
    });
27909
    const checkCharCode = (chars, event) => checkKeyEvent(chars, event, (chr, event) => {
27910
      return chr.charCodeAt(0) === event.charCode;
27911
    });
27912
 
27913
    const setup$2 = editor => {
27914
      const charCodes = [
27915
        ',',
27916
        '.',
27917
        ';',
27918
        ':',
27919
        '!',
27920
        '?'
27921
      ];
27922
      const keyCodes = [32];
27923
      const getPatternSet = () => createPatternSet(getTextPatterns(editor), getTextPatternsLookup(editor));
27924
      const hasDynamicPatterns = () => hasTextPatternsLookup(editor);
27925
      editor.on('keydown', e => {
27926
        if (e.keyCode === 13 && !VK.modifierPressed(e) && editor.selection.isCollapsed()) {
27927
          const patternSet = getPatternSet();
27928
          const hasPatterns = patternSet.inlinePatterns.length > 0 || patternSet.blockPatterns.length > 0 || hasDynamicPatterns();
27929
          if (hasPatterns && handleEnter(editor, patternSet)) {
27930
            e.preventDefault();
27931
          }
27932
        }
27933
      }, true);
27934
      const handleInlineTrigger = () => {
27935
        if (editor.selection.isCollapsed()) {
27936
          const patternSet = getPatternSet();
27937
          const hasPatterns = patternSet.inlinePatterns.length > 0 || hasDynamicPatterns();
27938
          if (hasPatterns) {
27939
            handleInlineKey(editor, patternSet);
27940
          }
27941
        }
27942
      };
27943
      editor.on('keyup', e => {
27944
        if (checkKeyCode(keyCodes, e)) {
27945
          handleInlineTrigger();
27946
        }
27947
      });
27948
      editor.on('keypress', e => {
27949
        if (checkCharCode(charCodes, e)) {
27950
          Delay.setEditorTimeout(editor, handleInlineTrigger);
27951
        }
27952
      });
27953
    };
27954
 
27955
    const setup$1 = editor => {
27956
      setup$2(editor);
27957
    };
27958
 
27959
    const Quirks = editor => {
27960
      const each = Tools.each;
27961
      const BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, parser = editor.parser;
27962
      const browser = Env.browser;
27963
      const isGecko = browser.isFirefox();
27964
      const isWebKit = browser.isChromium() || browser.isSafari();
27965
      const isiOS = Env.deviceType.isiPhone() || Env.deviceType.isiPad();
27966
      const isMac = Env.os.isMacOS() || Env.os.isiOS();
27967
      const setEditorCommandState = (cmd, state) => {
27968
        try {
27969
          editor.getDoc().execCommand(cmd, false, String(state));
27970
        } catch (ex) {
27971
        }
27972
      };
27973
      const isDefaultPrevented = e => {
27974
        return e.isDefaultPrevented();
27975
      };
27976
      const emptyEditorWhenDeleting = () => {
27977
        const serializeRng = rng => {
27978
          const body = dom.create('body');
27979
          const contents = rng.cloneContents();
27980
          body.appendChild(contents);
27981
          return selection.serializer.serialize(body, { format: 'html' });
27982
        };
27983
        const allContentsSelected = rng => {
27984
          const selection = serializeRng(rng);
27985
          const allRng = dom.createRng();
27986
          allRng.selectNode(editor.getBody());
27987
          const allSelection = serializeRng(allRng);
27988
          return selection === allSelection;
27989
        };
27990
        editor.on('keydown', e => {
27991
          const keyCode = e.keyCode;
27992
          if (!isDefaultPrevented(e) && (keyCode === DELETE || keyCode === BACKSPACE) && editor.selection.isEditable()) {
27993
            const isCollapsed = editor.selection.isCollapsed();
27994
            const body = editor.getBody();
27995
            if (isCollapsed && !isEmpty$2(SugarElement.fromDom(body))) {
27996
              return;
27997
            }
27998
            if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
27999
              return;
28000
            }
28001
            e.preventDefault();
28002
            editor.setContent('');
28003
            if (body.firstChild && dom.isBlock(body.firstChild)) {
28004
              editor.selection.setCursorLocation(body.firstChild, 0);
28005
            } else {
28006
              editor.selection.setCursorLocation(body, 0);
28007
            }
28008
            editor.nodeChanged();
28009
          }
28010
        });
28011
      };
28012
      const selectAll = () => {
28013
        editor.shortcuts.add('meta+a', null, 'SelectAll');
28014
      };
28015
      const documentElementEditingFocus = () => {
28016
        if (!editor.inline) {
28017
          dom.bind(editor.getDoc(), 'mousedown mouseup', e => {
28018
            let rng;
28019
            if (e.target === editor.getDoc().documentElement) {
28020
              rng = selection.getRng();
28021
              editor.getBody().focus();
28022
              if (e.type === 'mousedown') {
28023
                if (isCaretContainer$2(rng.startContainer)) {
28024
                  return;
28025
                }
28026
                selection.placeCaretAt(e.clientX, e.clientY);
28027
              } else {
28028
                selection.setRng(rng);
28029
              }
28030
            }
28031
          });
28032
        }
28033
      };
28034
      const removeHrOnBackspace = () => {
28035
        editor.on('keydown', e => {
28036
          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
28037
            if (!editor.getBody().getElementsByTagName('hr').length) {
28038
              return;
28039
            }
28040
            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
28041
              const node = selection.getNode();
28042
              const previousSibling = node.previousSibling;
28043
              if (node.nodeName === 'HR') {
28044
                dom.remove(node);
28045
                e.preventDefault();
28046
                return;
28047
              }
28048
              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'hr') {
28049
                dom.remove(previousSibling);
28050
                e.preventDefault();
28051
              }
28052
            }
28053
          }
28054
        });
28055
      };
28056
      const focusBody = () => {
28057
        if (!Range.prototype.getClientRects) {
28058
          editor.on('mousedown', e => {
28059
            if (!isDefaultPrevented(e) && e.target.nodeName === 'HTML') {
28060
              const body = editor.getBody();
28061
              body.blur();
28062
              Delay.setEditorTimeout(editor, () => {
28063
                body.focus();
28064
              });
28065
            }
28066
          });
28067
        }
28068
      };
28069
      const selectControlElements = () => {
28070
        const visualAidsAnchorClass = getVisualAidsAnchorClass(editor);
28071
        editor.on('click', e => {
28072
          const target = e.target;
28073
          if (/^(IMG|HR)$/.test(target.nodeName) && dom.isEditable(target)) {
28074
            e.preventDefault();
28075
            editor.selection.select(target);
28076
            editor.nodeChanged();
28077
          }
28078
          if (target.nodeName === 'A' && dom.hasClass(target, visualAidsAnchorClass) && target.childNodes.length === 0 && dom.isEditable(target.parentNode)) {
28079
            e.preventDefault();
28080
            selection.select(target);
28081
          }
28082
        });
28083
      };
28084
      const removeStylesWhenDeletingAcrossBlockElements = () => {
28085
        const getAttributeApplyFunction = () => {
28086
          const template = dom.getAttribs(selection.getStart().cloneNode(false));
28087
          return () => {
28088
            const target = selection.getStart();
28089
            if (target !== editor.getBody()) {
28090
              dom.setAttrib(target, 'style', null);
28091
              each(template, attr => {
28092
                target.setAttributeNode(attr.cloneNode(true));
28093
              });
28094
            }
28095
          };
28096
        };
28097
        const isSelectionAcrossElements = () => {
28098
          return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) !== dom.getParent(selection.getEnd(), dom.isBlock);
28099
        };
28100
        editor.on('keypress', e => {
28101
          let applyAttributes;
28102
          if (!isDefaultPrevented(e) && (e.keyCode === 8 || e.keyCode === 46) && isSelectionAcrossElements()) {
28103
            applyAttributes = getAttributeApplyFunction();
28104
            editor.getDoc().execCommand('delete', false);
28105
            applyAttributes();
28106
            e.preventDefault();
28107
            return false;
28108
          } else {
28109
            return true;
28110
          }
28111
        });
28112
        dom.bind(editor.getDoc(), 'cut', e => {
28113
          if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
28114
            const applyAttributes = getAttributeApplyFunction();
28115
            Delay.setEditorTimeout(editor, () => {
28116
              applyAttributes();
28117
            });
28118
          }
28119
        });
28120
      };
28121
      const disableBackspaceIntoATable = () => {
28122
        editor.on('keydown', e => {
28123
          if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
28124
            if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
28125
              const previousSibling = selection.getNode().previousSibling;
28126
              if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === 'table') {
28127
                e.preventDefault();
28128
                return false;
28129
              }
28130
            }
28131
          }
28132
          return true;
28133
        });
28134
      };
28135
      const removeBlockQuoteOnBackSpace = () => {
28136
        editor.on('keydown', e => {
28137
          if (isDefaultPrevented(e) || e.keyCode !== VK.BACKSPACE) {
28138
            return;
28139
          }
28140
          let rng = selection.getRng();
28141
          const container = rng.startContainer;
28142
          const offset = rng.startOffset;
28143
          const root = dom.getRoot();
28144
          let parent = container;
28145
          if (!rng.collapsed || offset !== 0) {
28146
            return;
28147
          }
28148
          while (parent.parentNode && parent.parentNode.firstChild === parent && parent.parentNode !== root) {
28149
            parent = parent.parentNode;
28150
          }
28151
          if (parent.nodeName === 'BLOCKQUOTE') {
28152
            editor.formatter.toggle('blockquote', undefined, parent);
28153
            rng = dom.createRng();
28154
            rng.setStart(container, 0);
28155
            rng.setEnd(container, 0);
28156
            selection.setRng(rng);
28157
          }
28158
        });
28159
      };
28160
      const setGeckoEditingOptions = () => {
28161
        const setOpts = () => {
28162
          setEditorCommandState('StyleWithCSS', false);
28163
          setEditorCommandState('enableInlineTableEditing', false);
28164
          if (!getObjectResizing(editor)) {
28165
            setEditorCommandState('enableObjectResizing', false);
28166
          }
28167
        };
28168
        if (!isReadOnly$1(editor)) {
28169
          editor.on('BeforeExecCommand mousedown', setOpts);
28170
        }
28171
      };
28172
      const addBrAfterLastLinks = () => {
28173
        const fixLinks = () => {
28174
          each(dom.select('a:not([data-mce-block])'), node => {
28175
            var _a;
28176
            let parentNode = node.parentNode;
28177
            const root = dom.getRoot();
28178
            if ((parentNode === null || parentNode === void 0 ? void 0 : parentNode.lastChild) === node) {
28179
              while (parentNode && !dom.isBlock(parentNode)) {
28180
                if (((_a = parentNode.parentNode) === null || _a === void 0 ? void 0 : _a.lastChild) !== parentNode || parentNode === root) {
28181
                  return;
28182
                }
28183
                parentNode = parentNode.parentNode;
28184
              }
28185
              dom.add(parentNode, 'br', { 'data-mce-bogus': 1 });
28186
            }
28187
          });
28188
        };
28189
        editor.on('SetContent ExecCommand', e => {
28190
          if (e.type === 'setcontent' || e.command === 'mceInsertLink') {
28191
            fixLinks();
28192
          }
28193
        });
28194
      };
28195
      const setDefaultBlockType = () => {
28196
        editor.on('init', () => {
28197
          setEditorCommandState('DefaultParagraphSeparator', getForcedRootBlock(editor));
28198
        });
28199
      };
28200
      const isAllContentSelected = editor => {
28201
        const body = editor.getBody();
28202
        const rng = editor.selection.getRng();
28203
        return rng.startContainer === rng.endContainer && rng.startContainer === body && rng.startOffset === 0 && rng.endOffset === body.childNodes.length;
28204
      };
28205
      const normalizeSelection = () => {
28206
        editor.on('keyup focusin mouseup', e => {
28207
          if (!VK.modifierPressed(e) && !isAllContentSelected(editor)) {
28208
            selection.normalize();
28209
          }
28210
        }, true);
28211
      };
28212
      const showBrokenImageIcon = () => {
28213
        editor.contentStyles.push('img:-moz-broken {' + '-moz-force-broken-image-icon:1;' + 'min-width:24px;' + 'min-height:24px' + '}');
28214
      };
28215
      const restoreFocusOnKeyDown = () => {
28216
        if (!editor.inline) {
28217
          editor.on('keydown', () => {
28218
            if (document.activeElement === document.body) {
28219
              editor.getWin().focus();
28220
            }
28221
          });
28222
        }
28223
      };
28224
      const bodyHeight = () => {
28225
        if (!editor.inline) {
28226
          editor.contentStyles.push('body {min-height: 150px}');
28227
          editor.on('click', e => {
28228
            let rng;
28229
            if (e.target.nodeName === 'HTML') {
28230
              rng = editor.selection.getRng();
28231
              editor.getBody().focus();
28232
              editor.selection.setRng(rng);
28233
              editor.selection.normalize();
28234
              editor.nodeChanged();
28235
            }
28236
          });
28237
        }
28238
      };
28239
      const blockCmdArrowNavigation = () => {
28240
        if (isMac) {
28241
          editor.on('keydown', e => {
28242
            if (VK.metaKeyPressed(e) && !e.shiftKey && (e.keyCode === 37 || e.keyCode === 39)) {
28243
              e.preventDefault();
28244
              const selection = editor.selection.getSel();
28245
              selection.modify('move', e.keyCode === 37 ? 'backward' : 'forward', 'lineboundary');
28246
            }
28247
          });
28248
        }
28249
      };
28250
      const tapLinksAndImages = () => {
28251
        editor.on('click', e => {
28252
          let elm = e.target;
28253
          do {
28254
            if (elm.tagName === 'A') {
28255
              e.preventDefault();
28256
              return;
28257
            }
28258
          } while (elm = elm.parentNode);
28259
        });
28260
        editor.contentStyles.push('.mce-content-body {-webkit-touch-callout: none}');
28261
      };
28262
      const blockFormSubmitInsideEditor = () => {
28263
        editor.on('init', () => {
28264
          editor.dom.bind(editor.getBody(), 'submit', e => {
28265
            e.preventDefault();
28266
          });
28267
        });
28268
      };
28269
      const removeAppleInterchangeBrs = () => {
28270
        parser.addNodeFilter('br', nodes => {
28271
          let i = nodes.length;
28272
          while (i--) {
28273
            if (nodes[i].attr('class') === 'Apple-interchange-newline') {
28274
              nodes[i].remove();
28275
            }
28276
          }
28277
        });
28278
      };
28279
      const refreshContentEditable = noop;
28280
      const isHidden = () => {
28281
        if (!isGecko || editor.removed) {
28282
          return false;
28283
        }
28284
        const sel = editor.selection.getSel();
28285
        return !sel || !sel.rangeCount || sel.rangeCount === 0;
28286
      };
28287
      const setupRtc = () => {
28288
        if (isWebKit) {
28289
          documentElementEditingFocus();
28290
          selectControlElements();
28291
          blockFormSubmitInsideEditor();
28292
          selectAll();
28293
          if (isiOS) {
28294
            restoreFocusOnKeyDown();
28295
            bodyHeight();
28296
            tapLinksAndImages();
28297
          }
28298
        }
28299
        if (isGecko) {
28300
          focusBody();
28301
          setGeckoEditingOptions();
28302
          showBrokenImageIcon();
28303
          blockCmdArrowNavigation();
28304
        }
28305
      };
28306
      const dropDragEndEvent = () => {
28307
        editor.on('drop', event => {
28308
          var _a;
28309
          const data = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData('text/html');
28310
          if (isString(data) && /^<img[^>]*>$/.test(data)) {
28311
            editor.dispatch('dragend', new window.DragEvent('dragend', event));
28312
          }
28313
        });
28314
      };
28315
      const setup = () => {
28316
        removeBlockQuoteOnBackSpace();
28317
        emptyEditorWhenDeleting();
28318
        if (!Env.windowsPhone) {
28319
          normalizeSelection();
28320
        }
28321
        if (isWebKit) {
28322
          documentElementEditingFocus();
28323
          selectControlElements();
28324
          setDefaultBlockType();
28325
          blockFormSubmitInsideEditor();
28326
          disableBackspaceIntoATable();
28327
          removeAppleInterchangeBrs();
28328
          if (isiOS) {
28329
            restoreFocusOnKeyDown();
28330
            bodyHeight();
28331
            tapLinksAndImages();
28332
          } else {
28333
            selectAll();
28334
          }
28335
        }
28336
        if (isGecko) {
28337
          removeHrOnBackspace();
28338
          focusBody();
28339
          removeStylesWhenDeletingAcrossBlockElements();
28340
          setGeckoEditingOptions();
28341
          addBrAfterLastLinks();
28342
          showBrokenImageIcon();
28343
          blockCmdArrowNavigation();
28344
          disableBackspaceIntoATable();
28345
          dropDragEndEvent();
28346
        }
28347
      };
28348
      if (isRtc(editor)) {
28349
        setupRtc();
28350
      } else {
28351
        setup();
28352
      }
28353
      return {
28354
        refreshContentEditable,
28355
        isHidden
28356
      };
28357
    };
28358
 
28359
    const DOM$6 = DOMUtils.DOM;
28360
    const appendStyle = (editor, text) => {
28361
      const body = SugarElement.fromDom(editor.getBody());
28362
      const container = getStyleContainer(getRootNode(body));
28363
      const style = SugarElement.fromTag('style');
28364
      set$3(style, 'type', 'text/css');
28365
      append$1(style, SugarElement.fromText(text));
28366
      append$1(container, style);
28367
      editor.on('remove', () => {
28368
        remove$5(style);
28369
      });
28370
    };
28371
    const getRootName = editor => editor.inline ? editor.getElement().nodeName.toLowerCase() : undefined;
28372
    const removeUndefined = obj => filter$4(obj, v => isUndefined(v) === false);
28373
    const mkParserSettings = editor => {
28374
      const getOption = editor.options.get;
28375
      const blobCache = editor.editorUpload.blobCache;
28376
      return removeUndefined({
28377
        allow_conditional_comments: getOption('allow_conditional_comments'),
28378
        allow_html_data_urls: getOption('allow_html_data_urls'),
28379
        allow_svg_data_urls: getOption('allow_svg_data_urls'),
28380
        allow_html_in_named_anchor: getOption('allow_html_in_named_anchor'),
28381
        allow_script_urls: getOption('allow_script_urls'),
28382
        allow_unsafe_link_target: getOption('allow_unsafe_link_target'),
28383
        convert_unsafe_embeds: getOption('convert_unsafe_embeds'),
28384
        convert_fonts_to_spans: getOption('convert_fonts_to_spans'),
28385
        fix_list_elements: getOption('fix_list_elements'),
28386
        font_size_legacy_values: getOption('font_size_legacy_values'),
28387
        forced_root_block: getOption('forced_root_block'),
28388
        forced_root_block_attrs: getOption('forced_root_block_attrs'),
28389
        preserve_cdata: getOption('preserve_cdata'),
28390
        inline_styles: getOption('inline_styles'),
28391
        root_name: getRootName(editor),
28392
        sandbox_iframes: getOption('sandbox_iframes'),
28393
        sanitize: getOption('xss_sanitization'),
28394
        validate: true,
28395
        blob_cache: blobCache,
28396
        document: editor.getDoc()
28397
      });
28398
    };
28399
    const mkSchemaSettings = editor => {
28400
      const getOption = editor.options.get;
28401
      return removeUndefined({
28402
        custom_elements: getOption('custom_elements'),
28403
        extended_valid_elements: getOption('extended_valid_elements'),
28404
        invalid_elements: getOption('invalid_elements'),
28405
        invalid_styles: getOption('invalid_styles'),
28406
        schema: getOption('schema'),
28407
        valid_children: getOption('valid_children'),
28408
        valid_classes: getOption('valid_classes'),
28409
        valid_elements: getOption('valid_elements'),
28410
        valid_styles: getOption('valid_styles'),
28411
        verify_html: getOption('verify_html'),
28412
        padd_empty_block_inline_children: getOption('format_empty_lines')
28413
      });
28414
    };
28415
    const mkSerializerSettings = editor => {
28416
      const getOption = editor.options.get;
28417
      return {
28418
        ...mkParserSettings(editor),
28419
        ...mkSchemaSettings(editor),
28420
        ...removeUndefined({
28421
          remove_trailing_brs: getOption('remove_trailing_brs'),
28422
          pad_empty_with_br: getOption('pad_empty_with_br'),
28423
          url_converter: getOption('url_converter'),
28424
          url_converter_scope: getOption('url_converter_scope'),
28425
          element_format: getOption('element_format'),
28426
          entities: getOption('entities'),
28427
          entity_encoding: getOption('entity_encoding'),
28428
          indent: getOption('indent'),
28429
          indent_after: getOption('indent_after'),
28430
          indent_before: getOption('indent_before')
28431
        })
28432
      };
28433
    };
28434
    const createParser = editor => {
28435
      const parser = DomParser(mkParserSettings(editor), editor.schema);
28436
      parser.addAttributeFilter('src,href,style,tabindex', (nodes, name) => {
28437
        const dom = editor.dom;
28438
        const internalName = 'data-mce-' + name;
28439
        let i = nodes.length;
28440
        while (i--) {
28441
          const node = nodes[i];
28442
          let value = node.attr(name);
28443
          if (value && !node.attr(internalName)) {
28444
            if (value.indexOf('data:') === 0 || value.indexOf('blob:') === 0) {
28445
              continue;
28446
            }
28447
            if (name === 'style') {
28448
              value = dom.serializeStyle(dom.parseStyle(value), node.name);
28449
              if (!value.length) {
28450
                value = null;
28451
              }
28452
              node.attr(internalName, value);
28453
              node.attr(name, value);
28454
            } else if (name === 'tabindex') {
28455
              node.attr(internalName, value);
28456
              node.attr(name, null);
28457
            } else {
28458
              node.attr(internalName, editor.convertURL(value, name, node.name));
28459
            }
28460
          }
28461
        }
28462
      });
28463
      parser.addNodeFilter('script', nodes => {
28464
        let i = nodes.length;
28465
        while (i--) {
28466
          const node = nodes[i];
28467
          const type = node.attr('type') || 'no/type';
28468
          if (type.indexOf('mce-') !== 0) {
28469
            node.attr('type', 'mce-' + type);
28470
          }
28471
        }
28472
      });
28473
      if (shouldPreserveCData(editor)) {
28474
        parser.addNodeFilter('#cdata', nodes => {
28475
          var _a;
28476
          let i = nodes.length;
28477
          while (i--) {
28478
            const node = nodes[i];
28479
            node.type = 8;
28480
            node.name = '#comment';
28481
            node.value = '[CDATA[' + editor.dom.encode((_a = node.value) !== null && _a !== void 0 ? _a : '') + ']]';
28482
          }
28483
        });
28484
      }
28485
      parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', nodes => {
28486
        let i = nodes.length;
28487
        const nonEmptyElements = editor.schema.getNonEmptyElements();
28488
        while (i--) {
28489
          const node = nodes[i];
28490
          if (node.isEmpty(nonEmptyElements) && node.getAll('br').length === 0) {
28491
            node.append(new AstNode('br', 1));
28492
          }
28493
        }
28494
      });
28495
      return parser;
28496
    };
28497
    const autoFocus = editor => {
28498
      const autoFocus = getAutoFocus(editor);
28499
      if (autoFocus) {
28500
        Delay.setEditorTimeout(editor, () => {
28501
          let focusEditor;
28502
          if (autoFocus === true) {
28503
            focusEditor = editor;
28504
          } else {
28505
            focusEditor = editor.editorManager.get(autoFocus);
28506
          }
28507
          if (focusEditor && !focusEditor.destroyed) {
28508
            focusEditor.focus();
28509
            focusEditor.selection.scrollIntoView();
28510
          }
28511
        }, 100);
28512
      }
28513
    };
28514
    const moveSelectionToFirstCaretPosition = editor => {
28515
      const root = editor.dom.getRoot();
28516
      if (!editor.inline && (!hasAnyRanges(editor) || editor.selection.getStart(true) === root)) {
28517
        firstPositionIn(root).each(pos => {
28518
          const node = pos.getNode();
28519
          const caretPos = isTable$2(node) ? firstPositionIn(node).getOr(pos) : pos;
28520
          editor.selection.setRng(caretPos.toRange());
28521
        });
28522
      }
28523
    };
28524
    const initEditor = editor => {
28525
      editor.bindPendingEventDelegates();
28526
      editor.initialized = true;
28527
      fireInit(editor);
28528
      editor.focus(true);
28529
      moveSelectionToFirstCaretPosition(editor);
28530
      editor.nodeChanged({ initial: true });
28531
      const initInstanceCallback = getInitInstanceCallback(editor);
28532
      if (isFunction(initInstanceCallback)) {
28533
        initInstanceCallback.call(editor, editor);
28534
      }
28535
      autoFocus(editor);
28536
    };
28537
    const getStyleSheetLoader$1 = editor => editor.inline ? editor.ui.styleSheetLoader : editor.dom.styleSheetLoader;
28538
    const makeStylesheetLoadingPromises = (editor, css, framedFonts) => {
28539
      const {
28540
        pass: bundledCss,
28541
        fail: normalCss
28542
      } = partition$2(css, name => tinymce.Resource.has(toContentSkinResourceName(name)));
28543
      const bundledPromises = bundledCss.map(url => {
28544
        const css = tinymce.Resource.get(toContentSkinResourceName(url));
28545
        if (isString(css)) {
28546
          return Promise.resolve(getStyleSheetLoader$1(editor).loadRawCss(url, css));
28547
        }
28548
        return Promise.resolve();
28549
      });
28550
      const promises = [
28551
        ...bundledPromises,
28552
        getStyleSheetLoader$1(editor).loadAll(normalCss)
28553
      ];
28554
      if (editor.inline) {
28555
        return promises;
28556
      } else {
28557
        return promises.concat([editor.ui.styleSheetLoader.loadAll(framedFonts)]);
28558
      }
28559
    };
28560
    const loadContentCss = editor => {
28561
      const styleSheetLoader = getStyleSheetLoader$1(editor);
28562
      const fontCss = getFontCss(editor);
28563
      const css = editor.contentCSS;
28564
      const removeCss = () => {
28565
        styleSheetLoader.unloadAll(css);
28566
        if (!editor.inline) {
28567
          editor.ui.styleSheetLoader.unloadAll(fontCss);
28568
        }
28569
      };
28570
      const loaded = () => {
28571
        if (editor.removed) {
28572
          removeCss();
28573
        } else {
28574
          editor.on('remove', removeCss);
28575
        }
28576
      };
28577
      if (editor.contentStyles.length > 0) {
28578
        let contentCssText = '';
28579
        Tools.each(editor.contentStyles, style => {
28580
          contentCssText += style + '\r\n';
28581
        });
28582
        editor.dom.addStyle(contentCssText);
28583
      }
28584
      const allStylesheets = Promise.all(makeStylesheetLoadingPromises(editor, css, fontCss)).then(loaded).catch(loaded);
28585
      const contentStyle = getContentStyle(editor);
28586
      if (contentStyle) {
28587
        appendStyle(editor, contentStyle);
28588
      }
28589
      return allStylesheets;
28590
    };
28591
    const preInit = editor => {
28592
      const doc = editor.getDoc(), body = editor.getBody();
28593
      firePreInit(editor);
28594
      if (!shouldBrowserSpellcheck(editor)) {
28595
        doc.body.spellcheck = false;
28596
        DOM$6.setAttrib(body, 'spellcheck', 'false');
28597
      }
28598
      editor.quirks = Quirks(editor);
28599
      firePostRender(editor);
28600
      const directionality = getDirectionality(editor);
28601
      if (directionality !== undefined) {
28602
        body.dir = directionality;
28603
      }
28604
      const protect = getProtect(editor);
28605
      if (protect) {
28606
        editor.on('BeforeSetContent', e => {
28607
          Tools.each(protect, pattern => {
28608
            e.content = e.content.replace(pattern, str => {
28609
              return '<!--mce:protected ' + escape(str) + '-->';
28610
            });
28611
          });
28612
        });
28613
      }
28614
      editor.on('SetContent', () => {
28615
        editor.addVisual(editor.getBody());
28616
      });
28617
      editor.on('compositionstart compositionend', e => {
28618
        editor.composing = e.type === 'compositionstart';
28619
      });
28620
    };
28621
    const loadInitialContent = editor => {
28622
      if (!isRtc(editor)) {
28623
        editor.load({
28624
          initial: true,
28625
          format: 'html'
28626
        });
28627
      }
28628
      editor.startContent = editor.getContent({ format: 'raw' });
28629
    };
28630
    const initEditorWithInitialContent = editor => {
28631
      if (editor.removed !== true) {
28632
        loadInitialContent(editor);
28633
        initEditor(editor);
28634
      }
28635
    };
28636
    const startProgress = editor => {
28637
      let canceled = false;
28638
      const progressTimeout = setTimeout(() => {
28639
        if (!canceled) {
28640
          editor.setProgressState(true);
28641
        }
28642
      }, 500);
28643
      return () => {
28644
        clearTimeout(progressTimeout);
28645
        canceled = true;
28646
        editor.setProgressState(false);
28647
      };
28648
    };
28649
    const contentBodyLoaded = editor => {
28650
      const targetElm = editor.getElement();
28651
      let doc = editor.getDoc();
28652
      if (editor.inline) {
28653
        DOM$6.addClass(targetElm, 'mce-content-body');
28654
        editor.contentDocument = doc = document;
28655
        editor.contentWindow = window;
28656
        editor.bodyElement = targetElm;
28657
        editor.contentAreaContainer = targetElm;
28658
      }
28659
      const body = editor.getBody();
28660
      body.disabled = true;
28661
      editor.readonly = isReadOnly$1(editor);
28662
      editor._editableRoot = hasEditableRoot$1(editor);
28663
      if (!editor.readonly && editor.hasEditableRoot()) {
28664
        if (editor.inline && DOM$6.getStyle(body, 'position', true) === 'static') {
28665
          body.style.position = 'relative';
28666
        }
28667
        body.contentEditable = 'true';
28668
      }
28669
      body.disabled = false;
28670
      editor.editorUpload = EditorUpload(editor);
28671
      editor.schema = Schema(mkSchemaSettings(editor));
28672
      editor.dom = DOMUtils(doc, {
28673
        keep_values: true,
28674
        url_converter: editor.convertURL,
28675
        url_converter_scope: editor,
28676
        update_styles: true,
28677
        root_element: editor.inline ? editor.getBody() : null,
28678
        collect: editor.inline,
28679
        schema: editor.schema,
28680
        contentCssCors: shouldUseContentCssCors(editor),
28681
        referrerPolicy: getReferrerPolicy(editor),
28682
        onSetAttrib: e => {
28683
          editor.dispatch('SetAttrib', e);
28684
        },
28685
        force_hex_color: shouldForceHexColor(editor)
28686
      });
28687
      editor.parser = createParser(editor);
28688
      editor.serializer = DomSerializer(mkSerializerSettings(editor), editor);
28689
      editor.selection = EditorSelection(editor.dom, editor.getWin(), editor.serializer, editor);
28690
      editor.annotator = Annotator(editor);
28691
      editor.formatter = Formatter(editor);
28692
      editor.undoManager = UndoManager(editor);
28693
      editor._nodeChangeDispatcher = new NodeChange(editor);
28694
      editor._selectionOverrides = SelectionOverrides(editor);
28695
      setup$p(editor);
28696
      setup$6(editor);
28697
      setup$n(editor);
28698
      if (!isRtc(editor)) {
28699
        setup$5(editor);
28700
        setup$1(editor);
28701
      }
28702
      const caret = setup$b(editor);
28703
      setup$q(editor, caret);
28704
      setup$o(editor);
28705
      setup$r(editor);
28706
      setup$7(editor);
28707
      const setupRtcThunk = setup$t(editor);
28708
      preInit(editor);
28709
      setupRtcThunk.fold(() => {
28710
        const cancelProgress = startProgress(editor);
28711
        loadContentCss(editor).then(() => {
28712
          initEditorWithInitialContent(editor);
28713
          cancelProgress();
28714
        });
28715
      }, setupRtc => {
28716
        editor.setProgressState(true);
28717
        loadContentCss(editor).then(() => {
28718
          setupRtc().then(_rtcMode => {
28719
            editor.setProgressState(false);
28720
            initEditorWithInitialContent(editor);
28721
            bindEvents(editor);
28722
          }, err => {
28723
            editor.notificationManager.open({
28724
              type: 'error',
28725
              text: String(err)
28726
            });
28727
            initEditorWithInitialContent(editor);
28728
            bindEvents(editor);
28729
          });
28730
        });
28731
      });
28732
    };
28733
 
28734
    const filter = always;
28735
    const bind = (element, event, handler) => bind$2(element, event, filter, handler);
28736
 
28737
    const DOM$5 = DOMUtils.DOM;
28738
    const createIframeElement = (id, title, customAttrs, tabindex) => {
28739
      const iframe = SugarElement.fromTag('iframe');
28740
      tabindex.each(t => set$3(iframe, 'tabindex', t));
28741
      setAll$1(iframe, customAttrs);
28742
      setAll$1(iframe, {
28743
        id: id + '_ifr',
28744
        frameBorder: '0',
28745
        allowTransparency: 'true',
28746
        title
28747
      });
28748
      add$2(iframe, 'tox-edit-area__iframe');
28749
      return iframe;
28750
    };
28751
    const getIframeHtml = editor => {
28752
      let iframeHTML = getDocType(editor) + '<html><head>';
28753
      if (getDocumentBaseUrl(editor) !== editor.documentBaseUrl) {
28754
        iframeHTML += '<base href="' + editor.documentBaseURI.getURI() + '" />';
28755
      }
28756
      iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
28757
      const bodyId = getBodyId(editor);
28758
      const bodyClass = getBodyClass(editor);
28759
      const translatedAriaText = editor.translate(getIframeAriaText(editor));
28760
      if (getContentSecurityPolicy(editor)) {
28761
        iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + getContentSecurityPolicy(editor) + '" />';
28762
      }
28763
      iframeHTML += '</head>' + `<body id="${ bodyId }" class="mce-content-body ${ bodyClass }" data-id="${ editor.id }" aria-label="${ translatedAriaText }">` + '<br>' + '</body></html>';
28764
      return iframeHTML;
28765
    };
28766
    const createIframe = (editor, boxInfo) => {
28767
      const iframeTitle = editor.translate('Rich Text Area');
28768
      const tabindex = getOpt(SugarElement.fromDom(editor.getElement()), 'tabindex').bind(toInt);
28769
      const ifr = createIframeElement(editor.id, iframeTitle, getIframeAttrs(editor), tabindex).dom;
28770
      ifr.onload = () => {
28771
        ifr.onload = null;
28772
        editor.dispatch('load');
28773
      };
28774
      editor.contentAreaContainer = boxInfo.iframeContainer;
28775
      editor.iframeElement = ifr;
28776
      editor.iframeHTML = getIframeHtml(editor);
28777
      DOM$5.add(boxInfo.iframeContainer, ifr);
28778
    };
28779
    const setupIframeBody = editor => {
28780
      const iframe = editor.iframeElement;
28781
      const ready = () => {
28782
        editor.contentDocument = iframe.contentDocument;
28783
        contentBodyLoaded(editor);
28784
      };
28785
      if (shouldUseDocumentWrite(editor) || Env.browser.isFirefox()) {
28786
        const doc = editor.getDoc();
28787
        doc.open();
28788
        doc.write(editor.iframeHTML);
28789
        doc.close();
28790
        ready();
28791
      } else {
28792
        const binder = bind(SugarElement.fromDom(iframe), 'load', () => {
28793
          binder.unbind();
28794
          ready();
28795
        });
28796
        iframe.srcdoc = editor.iframeHTML;
28797
      }
28798
    };
28799
    const init$1 = (editor, boxInfo) => {
28800
      createIframe(editor, boxInfo);
28801
      if (boxInfo.editorContainer) {
28802
        boxInfo.editorContainer.style.display = editor.orgDisplay;
28803
        editor.hidden = DOM$5.isHidden(boxInfo.editorContainer);
28804
      }
28805
      editor.getElement().style.display = 'none';
28806
      DOM$5.setAttrib(editor.id, 'aria-hidden', 'true');
28807
      editor.getElement().style.visibility = editor.orgVisibility;
28808
      setupIframeBody(editor);
28809
    };
28810
 
28811
    const DOM$4 = DOMUtils.DOM;
28812
    const initPlugin = (editor, initializedPlugins, plugin) => {
28813
      const Plugin = PluginManager.get(plugin);
28814
      const pluginUrl = PluginManager.urls[plugin] || editor.documentBaseUrl.replace(/\/$/, '');
28815
      plugin = Tools.trim(plugin);
28816
      if (Plugin && Tools.inArray(initializedPlugins, plugin) === -1) {
28817
        if (editor.plugins[plugin]) {
28818
          return;
28819
        }
28820
        try {
28821
          const pluginInstance = Plugin(editor, pluginUrl) || {};
28822
          editor.plugins[plugin] = pluginInstance;
28823
          if (isFunction(pluginInstance.init)) {
28824
            pluginInstance.init(editor, pluginUrl);
28825
            initializedPlugins.push(plugin);
28826
          }
28827
        } catch (e) {
28828
          pluginInitError(editor, plugin, e);
28829
        }
28830
      }
28831
    };
28832
    const trimLegacyPrefix = name => {
28833
      return name.replace(/^\-/, '');
28834
    };
28835
    const initPlugins = editor => {
28836
      const initializedPlugins = [];
28837
      each$e(getPlugins(editor), name => {
28838
        initPlugin(editor, initializedPlugins, trimLegacyPrefix(name));
28839
      });
28840
    };
28841
    const initIcons = editor => {
28842
      const iconPackName = Tools.trim(getIconPackName(editor));
28843
      const currentIcons = editor.ui.registry.getAll().icons;
28844
      const loadIcons = {
28845
        ...IconManager.get('default').icons,
28846
        ...IconManager.get(iconPackName).icons
28847
      };
28848
      each$d(loadIcons, (svgData, icon) => {
28849
        if (!has$2(currentIcons, icon)) {
28850
          editor.ui.registry.addIcon(icon, svgData);
28851
        }
28852
      });
28853
    };
28854
    const initTheme = editor => {
28855
      const theme = getTheme(editor);
28856
      if (isString(theme)) {
28857
        const Theme = ThemeManager.get(theme);
28858
        editor.theme = Theme(editor, ThemeManager.urls[theme]) || {};
28859
        if (isFunction(editor.theme.init)) {
28860
          editor.theme.init(editor, ThemeManager.urls[theme] || editor.documentBaseUrl.replace(/\/$/, ''));
28861
        }
28862
      } else {
28863
        editor.theme = {};
28864
      }
28865
    };
28866
    const initModel = editor => {
28867
      const model = getModel(editor);
28868
      const Model = ModelManager.get(model);
28869
      editor.model = Model(editor, ModelManager.urls[model]);
28870
    };
28871
    const renderFromLoadedTheme = editor => {
28872
      const render = editor.theme.renderUI;
28873
      return render ? render() : renderThemeFalse(editor);
28874
    };
28875
    const renderFromThemeFunc = editor => {
28876
      const elm = editor.getElement();
28877
      const theme = getTheme(editor);
28878
      const info = theme(editor, elm);
28879
      if (info.editorContainer.nodeType) {
28880
        info.editorContainer.id = info.editorContainer.id || editor.id + '_parent';
28881
      }
28882
      if (info.iframeContainer && info.iframeContainer.nodeType) {
28883
        info.iframeContainer.id = info.iframeContainer.id || editor.id + '_iframecontainer';
28884
      }
28885
      info.height = info.iframeHeight ? info.iframeHeight : elm.offsetHeight;
28886
      return info;
28887
    };
28888
    const createThemeFalseResult = (element, iframe) => {
28889
      return {
28890
        editorContainer: element,
28891
        iframeContainer: iframe,
28892
        api: {}
28893
      };
28894
    };
28895
    const renderThemeFalseIframe = targetElement => {
28896
      const iframeContainer = DOM$4.create('div');
28897
      DOM$4.insertAfter(iframeContainer, targetElement);
28898
      return createThemeFalseResult(iframeContainer, iframeContainer);
28899
    };
28900
    const renderThemeFalse = editor => {
28901
      const targetElement = editor.getElement();
28902
      return editor.inline ? createThemeFalseResult(null) : renderThemeFalseIframe(targetElement);
28903
    };
28904
    const renderThemeUi = editor => {
28905
      const elm = editor.getElement();
28906
      editor.orgDisplay = elm.style.display;
28907
      if (isString(getTheme(editor))) {
28908
        return renderFromLoadedTheme(editor);
28909
      } else if (isFunction(getTheme(editor))) {
28910
        return renderFromThemeFunc(editor);
28911
      } else {
28912
        return renderThemeFalse(editor);
28913
      }
28914
    };
28915
    const augmentEditorUiApi = (editor, api) => {
28916
      const uiApiFacade = {
28917
        show: Optional.from(api.show).getOr(noop),
28918
        hide: Optional.from(api.hide).getOr(noop),
28919
        isEnabled: Optional.from(api.isEnabled).getOr(always),
28920
        setEnabled: state => {
28921
          if (!editor.mode.isReadOnly()) {
28922
            Optional.from(api.setEnabled).each(f => f(state));
28923
          }
28924
        }
28925
      };
28926
      editor.ui = {
28927
        ...editor.ui,
28928
        ...uiApiFacade
28929
      };
28930
    };
28931
    const init = async editor => {
28932
      editor.dispatch('ScriptsLoaded');
28933
      initIcons(editor);
28934
      initTheme(editor);
28935
      initModel(editor);
28936
      initPlugins(editor);
28937
      const renderInfo = await renderThemeUi(editor);
28938
      augmentEditorUiApi(editor, Optional.from(renderInfo.api).getOr({}));
28939
      editor.editorContainer = renderInfo.editorContainer;
28940
      appendContentCssFromSettings(editor);
28941
      if (editor.inline) {
28942
        contentBodyLoaded(editor);
28943
      } else {
28944
        init$1(editor, {
28945
          editorContainer: renderInfo.editorContainer,
28946
          iframeContainer: renderInfo.iframeContainer
28947
        });
28948
      }
28949
    };
28950
 
28951
    const DOM$3 = DOMUtils.DOM;
28952
    const hasSkipLoadPrefix = name => name.charAt(0) === '-';
28953
    const loadLanguage = (scriptLoader, editor) => {
28954
      const languageCode = getLanguageCode(editor);
28955
      const languageUrl = getLanguageUrl(editor);
28956
      if (!I18n.hasCode(languageCode) && languageCode !== 'en') {
28957
        const url = isNotEmpty(languageUrl) ? languageUrl : `${ editor.editorManager.baseURL }/langs/${ languageCode }.js`;
28958
        scriptLoader.add(url).catch(() => {
28959
          languageLoadError(editor, url, languageCode);
28960
        });
28961
      }
28962
    };
28963
    const loadTheme = (editor, suffix) => {
28964
      const theme = getTheme(editor);
28965
      if (isString(theme) && !hasSkipLoadPrefix(theme) && !has$2(ThemeManager.urls, theme)) {
28966
        const themeUrl = getThemeUrl(editor);
28967
        const url = themeUrl ? editor.documentBaseURI.toAbsolute(themeUrl) : `themes/${ theme }/theme${ suffix }.js`;
28968
        ThemeManager.load(theme, url).catch(() => {
28969
          themeLoadError(editor, url, theme);
28970
        });
28971
      }
28972
    };
28973
    const loadModel = (editor, suffix) => {
28974
      const model = getModel(editor);
28975
      if (model !== 'plugin' && !has$2(ModelManager.urls, model)) {
28976
        const modelUrl = getModelUrl(editor);
28977
        const url = isString(modelUrl) ? editor.documentBaseURI.toAbsolute(modelUrl) : `models/${ model }/model${ suffix }.js`;
28978
        ModelManager.load(model, url).catch(() => {
28979
          modelLoadError(editor, url, model);
28980
        });
28981
      }
28982
    };
28983
    const getIconsUrlMetaFromUrl = editor => Optional.from(getIconsUrl(editor)).filter(isNotEmpty).map(url => ({
28984
      url,
28985
      name: Optional.none()
28986
    }));
28987
    const getIconsUrlMetaFromName = (editor, name, suffix) => Optional.from(name).filter(name => isNotEmpty(name) && !IconManager.has(name)).map(name => ({
28988
      url: `${ editor.editorManager.baseURL }/icons/${ name }/icons${ suffix }.js`,
28989
      name: Optional.some(name)
28990
    }));
28991
    const loadIcons = (scriptLoader, editor, suffix) => {
28992
      const defaultIconsUrl = getIconsUrlMetaFromName(editor, 'default', suffix);
28993
      const customIconsUrl = getIconsUrlMetaFromUrl(editor).orThunk(() => getIconsUrlMetaFromName(editor, getIconPackName(editor), ''));
28994
      each$e(cat([
28995
        defaultIconsUrl,
28996
        customIconsUrl
28997
      ]), urlMeta => {
28998
        scriptLoader.add(urlMeta.url).catch(() => {
28999
          iconsLoadError(editor, urlMeta.url, urlMeta.name.getOrUndefined());
29000
        });
29001
      });
29002
    };
29003
    const loadPlugins = (editor, suffix) => {
29004
      const loadPlugin = (name, url) => {
29005
        PluginManager.load(name, url).catch(() => {
29006
          pluginLoadError(editor, url, name);
29007
        });
29008
      };
29009
      each$d(getExternalPlugins$1(editor), (url, name) => {
29010
        loadPlugin(name, url);
29011
        editor.options.set('plugins', getPlugins(editor).concat(name));
29012
      });
29013
      each$e(getPlugins(editor), plugin => {
29014
        plugin = Tools.trim(plugin);
29015
        if (plugin && !PluginManager.urls[plugin] && !hasSkipLoadPrefix(plugin)) {
29016
          loadPlugin(plugin, `plugins/${ plugin }/plugin${ suffix }.js`);
29017
        }
29018
      });
29019
    };
29020
    const isThemeLoaded = editor => {
29021
      const theme = getTheme(editor);
29022
      return !isString(theme) || isNonNullable(ThemeManager.get(theme));
29023
    };
29024
    const isModelLoaded = editor => {
29025
      const model = getModel(editor);
29026
      return isNonNullable(ModelManager.get(model));
29027
    };
29028
    const loadScripts = (editor, suffix) => {
29029
      const scriptLoader = ScriptLoader.ScriptLoader;
29030
      const initEditor = () => {
29031
        if (!editor.removed && isThemeLoaded(editor) && isModelLoaded(editor)) {
29032
          init(editor);
29033
        }
29034
      };
29035
      loadTheme(editor, suffix);
29036
      loadModel(editor, suffix);
29037
      loadLanguage(scriptLoader, editor);
29038
      loadIcons(scriptLoader, editor, suffix);
29039
      loadPlugins(editor, suffix);
29040
      scriptLoader.loadQueue().then(initEditor, initEditor);
29041
    };
29042
    const getStyleSheetLoader = (element, editor) => instance.forElement(element, {
29043
      contentCssCors: hasContentCssCors(editor),
29044
      referrerPolicy: getReferrerPolicy(editor)
29045
    });
29046
    const render = editor => {
29047
      const id = editor.id;
29048
      I18n.setCode(getLanguageCode(editor));
29049
      const readyHandler = () => {
29050
        DOM$3.unbind(window, 'ready', readyHandler);
29051
        editor.render();
29052
      };
29053
      if (!EventUtils.Event.domLoaded) {
29054
        DOM$3.bind(window, 'ready', readyHandler);
29055
        return;
29056
      }
29057
      if (!editor.getElement()) {
29058
        return;
29059
      }
29060
      const element = SugarElement.fromDom(editor.getElement());
29061
      const snapshot = clone$4(element);
29062
      editor.on('remove', () => {
29063
        eachr(element.dom.attributes, attr => remove$a(element, attr.name));
29064
        setAll$1(element, snapshot);
29065
      });
29066
      editor.ui.styleSheetLoader = getStyleSheetLoader(element, editor);
29067
      if (!isInline$1(editor)) {
29068
        editor.orgVisibility = editor.getElement().style.visibility;
29069
        editor.getElement().style.visibility = 'hidden';
29070
      } else {
29071
        editor.inline = true;
29072
      }
29073
      const form = editor.getElement().form || DOM$3.getParent(id, 'form');
29074
      if (form) {
29075
        editor.formElement = form;
29076
        if (hasHiddenInput(editor) && !isTextareaOrInput(editor.getElement())) {
29077
          DOM$3.insertAfter(DOM$3.create('input', {
29078
            type: 'hidden',
29079
            name: id
29080
          }), id);
29081
          editor.hasHiddenInput = true;
29082
        }
29083
        editor.formEventDelegate = e => {
29084
          editor.dispatch(e.type, e);
29085
        };
29086
        DOM$3.bind(form, 'submit reset', editor.formEventDelegate);
29087
        editor.on('reset', () => {
29088
          editor.resetContent();
29089
        });
29090
        if (shouldPatchSubmit(editor) && !form.submit.nodeType && !form.submit.length && !form._mceOldSubmit) {
29091
          form._mceOldSubmit = form.submit;
29092
          form.submit = () => {
29093
            editor.editorManager.triggerSave();
29094
            editor.setDirty(false);
29095
            return form._mceOldSubmit(form);
29096
          };
29097
        }
29098
      }
29099
      editor.windowManager = WindowManager(editor);
29100
      editor.notificationManager = NotificationManager(editor);
29101
      if (isEncodingXml(editor)) {
29102
        editor.on('GetContent', e => {
29103
          if (e.save) {
29104
            e.content = DOM$3.encode(e.content);
29105
          }
29106
        });
29107
      }
29108
      if (shouldAddFormSubmitTrigger(editor)) {
29109
        editor.on('submit', () => {
29110
          if (editor.initialized) {
29111
            editor.save();
29112
          }
29113
        });
29114
      }
29115
      if (shouldAddUnloadTrigger(editor)) {
29116
        editor._beforeUnload = () => {
29117
          if (editor.initialized && !editor.destroyed && !editor.isHidden()) {
29118
            editor.save({
29119
              format: 'raw',
29120
              no_events: true,
29121
              set_dirty: false
29122
            });
29123
          }
29124
        };
29125
        editor.editorManager.on('BeforeUnload', editor._beforeUnload);
29126
      }
29127
      editor.editorManager.add(editor);
29128
      loadScripts(editor, editor.suffix);
29129
    };
29130
 
29131
    const setEditableRoot = (editor, state) => {
29132
      if (editor._editableRoot !== state) {
29133
        editor._editableRoot = state;
29134
        if (!editor.readonly) {
29135
          editor.getBody().contentEditable = String(editor.hasEditableRoot());
29136
          editor.nodeChanged();
29137
        }
29138
        fireEditableRootStateChange(editor, state);
29139
      }
29140
    };
29141
    const hasEditableRoot = editor => editor._editableRoot;
29142
 
29143
    const sectionResult = (sections, settings) => ({
29144
      sections: constant(sections),
29145
      options: constant(settings)
29146
    });
29147
    const deviceDetection = detect$2().deviceType;
29148
    const isPhone = deviceDetection.isPhone();
29149
    const isTablet = deviceDetection.isTablet();
29150
    const normalizePlugins = plugins => {
29151
      if (isNullable(plugins)) {
29152
        return [];
29153
      } else {
29154
        const pluginNames = isArray$1(plugins) ? plugins : plugins.split(/[ ,]/);
29155
        const trimmedPlugins = map$3(pluginNames, trim$4);
29156
        return filter$5(trimmedPlugins, isNotEmpty);
29157
      }
29158
    };
29159
    const extractSections = (keys, options) => {
29160
      const result = bifilter(options, (value, key) => {
29161
        return contains$2(keys, key);
29162
      });
29163
      return sectionResult(result.t, result.f);
29164
    };
29165
    const getSection = (sectionResult, name, defaults = {}) => {
29166
      const sections = sectionResult.sections();
29167
      const sectionOptions = get$a(sections, name).getOr({});
29168
      return Tools.extend({}, defaults, sectionOptions);
29169
    };
29170
    const hasSection = (sectionResult, name) => {
29171
      return has$2(sectionResult.sections(), name);
29172
    };
29173
    const getSectionConfig = (sectionResult, name) => {
29174
      return hasSection(sectionResult, name) ? sectionResult.sections()[name] : {};
29175
    };
29176
    const getMobileOverrideOptions = (mobileOptions, isPhone) => {
29177
      const defaultMobileOptions = {
29178
        table_grid: false,
29179
        object_resizing: false,
29180
        resize: false,
29181
        toolbar_mode: get$a(mobileOptions, 'toolbar_mode').getOr('scrolling'),
29182
        toolbar_sticky: false
29183
      };
29184
      const defaultPhoneOptions = { menubar: false };
29185
      return {
29186
        ...defaultMobileOptions,
29187
        ...isPhone ? defaultPhoneOptions : {}
29188
      };
29189
    };
29190
    const getExternalPlugins = (overrideOptions, options) => {
29191
      var _a;
29192
      const userDefinedExternalPlugins = (_a = options.external_plugins) !== null && _a !== void 0 ? _a : {};
29193
      if (overrideOptions && overrideOptions.external_plugins) {
29194
        return Tools.extend({}, overrideOptions.external_plugins, userDefinedExternalPlugins);
29195
      } else {
29196
        return userDefinedExternalPlugins;
29197
      }
29198
    };
29199
    const combinePlugins = (forcedPlugins, plugins) => [
29200
      ...normalizePlugins(forcedPlugins),
29201
      ...normalizePlugins(plugins)
29202
    ];
29203
    const getPlatformPlugins = (isMobileDevice, sectionResult, desktopPlugins, mobilePlugins) => {
29204
      if (isMobileDevice && hasSection(sectionResult, 'mobile')) {
29205
        return mobilePlugins;
29206
      } else {
29207
        return desktopPlugins;
29208
      }
29209
    };
29210
    const processPlugins = (isMobileDevice, sectionResult, defaultOverrideOptions, options) => {
29211
      const forcedPlugins = normalizePlugins(defaultOverrideOptions.forced_plugins);
29212
      const desktopPlugins = normalizePlugins(options.plugins);
29213
      const mobileConfig = getSectionConfig(sectionResult, 'mobile');
29214
      const mobilePlugins = mobileConfig.plugins ? normalizePlugins(mobileConfig.plugins) : desktopPlugins;
29215
      const platformPlugins = getPlatformPlugins(isMobileDevice, sectionResult, desktopPlugins, mobilePlugins);
29216
      const combinedPlugins = combinePlugins(forcedPlugins, platformPlugins);
29217
      return Tools.extend(options, {
29218
        forced_plugins: forcedPlugins,
29219
        plugins: combinedPlugins
29220
      });
29221
    };
29222
    const isOnMobile = (isMobileDevice, sectionResult) => {
29223
      return isMobileDevice && hasSection(sectionResult, 'mobile');
29224
    };
29225
    const combineOptions = (isMobileDevice, isPhone, defaultOptions, defaultOverrideOptions, options) => {
29226
      var _a;
29227
      const deviceOverrideOptions = isMobileDevice ? { mobile: getMobileOverrideOptions((_a = options.mobile) !== null && _a !== void 0 ? _a : {}, isPhone) } : {};
29228
      const sectionResult = extractSections(['mobile'], deepMerge(deviceOverrideOptions, options));
29229
      const extendedOptions = Tools.extend(defaultOptions, defaultOverrideOptions, sectionResult.options(), isOnMobile(isMobileDevice, sectionResult) ? getSection(sectionResult, 'mobile') : {}, { external_plugins: getExternalPlugins(defaultOverrideOptions, sectionResult.options()) });
29230
      return processPlugins(isMobileDevice, sectionResult, defaultOverrideOptions, extendedOptions);
29231
    };
29232
    const normalizeOptions = (defaultOverrideOptions, options) => combineOptions(isPhone || isTablet, isPhone, options, defaultOverrideOptions, options);
29233
 
29234
    const addVisual = (editor, elm) => addVisual$1(editor, elm);
29235
 
29236
    const registerExecCommands$3 = editor => {
29237
      const toggleFormat = (name, value) => {
29238
        editor.formatter.toggle(name, value);
29239
        editor.nodeChanged();
29240
      };
29241
      const toggleAlign = align => () => {
29242
        each$e('left,center,right,justify'.split(','), name => {
29243
          if (align !== name) {
29244
            editor.formatter.remove('align' + name);
29245
          }
29246
        });
29247
        if (align !== 'none') {
29248
          toggleFormat('align' + align);
29249
        }
29250
      };
29251
      editor.editorCommands.addCommands({
29252
        JustifyLeft: toggleAlign('left'),
29253
        JustifyCenter: toggleAlign('center'),
29254
        JustifyRight: toggleAlign('right'),
29255
        JustifyFull: toggleAlign('justify'),
29256
        JustifyNone: toggleAlign('none')
29257
      });
29258
    };
29259
    const registerQueryStateCommands$1 = editor => {
29260
      const alignStates = name => () => {
29261
        const selection = editor.selection;
29262
        const nodes = selection.isCollapsed() ? [editor.dom.getParent(selection.getNode(), editor.dom.isBlock)] : selection.getSelectedBlocks();
29263
        return exists(nodes, node => isNonNullable(editor.formatter.matchNode(node, name)));
29264
      };
29265
      editor.editorCommands.addCommands({
29266
        JustifyLeft: alignStates('alignleft'),
29267
        JustifyCenter: alignStates('aligncenter'),
29268
        JustifyRight: alignStates('alignright'),
29269
        JustifyFull: alignStates('alignjustify')
29270
      }, 'state');
29271
    };
29272
    const registerCommands$b = editor => {
29273
      registerExecCommands$3(editor);
29274
      registerQueryStateCommands$1(editor);
29275
    };
29276
 
29277
    const registerCommands$a = editor => {
29278
      editor.editorCommands.addCommands({
29279
        'Cut,Copy,Paste': command => {
29280
          const doc = editor.getDoc();
29281
          let failed;
29282
          try {
29283
            doc.execCommand(command);
29284
          } catch (ex) {
29285
            failed = true;
29286
          }
29287
          if (command === 'paste' && !doc.queryCommandEnabled(command)) {
29288
            failed = true;
29289
          }
29290
          if (failed || !doc.queryCommandSupported(command)) {
29291
            let msg = editor.translate(`Your browser doesn't support direct access to the clipboard. ` + 'Please use the Ctrl+X/C/V keyboard shortcuts instead.');
29292
            if (Env.os.isMacOS() || Env.os.isiOS()) {
29293
              msg = msg.replace(/Ctrl\+/g, '\u2318+');
29294
            }
29295
            editor.notificationManager.open({
29296
              text: msg,
29297
              type: 'error'
29298
            });
29299
          }
29300
        }
29301
      });
29302
    };
29303
 
29304
    const trimOrPadLeftRight = (dom, rng, html, schema) => {
29305
      const root = SugarElement.fromDom(dom.getRoot());
29306
      if (needsToBeNbspLeft(root, CaretPosition.fromRangeStart(rng), schema)) {
29307
        html = html.replace(/^ /, '&nbsp;');
29308
      } else {
29309
        html = html.replace(/^&nbsp;/, ' ');
29310
      }
29311
      if (needsToBeNbspRight(root, CaretPosition.fromRangeEnd(rng), schema)) {
29312
        html = html.replace(/(&nbsp;| )(<br( \/)>)?$/, '&nbsp;');
29313
      } else {
29314
        html = html.replace(/&nbsp;(<br( \/)?>)?$/, ' ');
29315
      }
29316
      return html;
29317
    };
29318
 
29319
    const processValue$1 = value => {
29320
      if (typeof value !== 'string') {
29321
        const details = Tools.extend({
29322
          paste: value.paste,
29323
          data: { paste: value.paste }
29324
        }, value);
29325
        return {
29326
          content: value.content,
29327
          details
29328
        };
29329
      }
29330
      return {
29331
        content: value,
29332
        details: {}
29333
      };
29334
    };
29335
    const trimOrPad = (editor, value) => {
29336
      const selection = editor.selection;
29337
      const dom = editor.dom;
29338
      if (/^ | $/.test(value)) {
29339
        return trimOrPadLeftRight(dom, selection.getRng(), value, editor.schema);
29340
      } else {
29341
        return value;
29342
      }
29343
    };
29344
    const insertAtCaret = (editor, value) => {
29345
      if (editor.selection.isEditable()) {
29346
        const {content, details} = processValue$1(value);
29347
        preProcessSetContent(editor, {
29348
          ...details,
29349
          content: trimOrPad(editor, content),
29350
          format: 'html',
29351
          set: false,
29352
          selection: true
29353
        }).each(args => {
29354
          const insertedContent = insertContent$1(editor, args.content, details);
29355
          postProcessSetContent(editor, insertedContent, args);
29356
          editor.addVisual();
29357
        });
29358
      }
29359
    };
29360
 
29361
    const registerCommands$9 = editor => {
29362
      editor.editorCommands.addCommands({
29363
        mceCleanup: () => {
29364
          const bm = editor.selection.getBookmark();
29365
          editor.setContent(editor.getContent());
29366
          editor.selection.moveToBookmark(bm);
29367
        },
29368
        insertImage: (_command, _ui, value) => {
29369
          insertAtCaret(editor, editor.dom.createHTML('img', { src: value }));
29370
        },
29371
        insertHorizontalRule: () => {
29372
          editor.execCommand('mceInsertContent', false, '<hr>');
29373
        },
29374
        insertText: (_command, _ui, value) => {
29375
          insertAtCaret(editor, editor.dom.encode(value));
29376
        },
29377
        insertHTML: (_command, _ui, value) => {
29378
          insertAtCaret(editor, value);
29379
        },
29380
        mceInsertContent: (_command, _ui, value) => {
29381
          insertAtCaret(editor, value);
29382
        },
29383
        mceSetContent: (_command, _ui, value) => {
29384
          editor.setContent(value);
29385
        },
29386
        mceReplaceContent: (_command, _ui, value) => {
29387
          editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, editor.selection.getContent({ format: 'text' })));
29388
        },
29389
        mceNewDocument: () => {
29390
          editor.setContent(getNewDocumentContent(editor));
29391
        }
29392
      });
29393
    };
29394
 
29395
    const legacyPropNames = {
29396
      'font-size': 'size',
29397
      'font-family': 'face'
29398
    };
29399
    const isFont = isTag('font');
29400
    const getSpecifiedFontProp = (propName, rootElm, elm) => {
29401
      const getProperty = elm => getRaw(elm, propName).orThunk(() => {
29402
        if (isFont(elm)) {
29403
          return get$a(legacyPropNames, propName).bind(legacyPropName => getOpt(elm, legacyPropName));
29404
        } else {
29405
          return Optional.none();
29406
        }
29407
      });
29408
      const isRoot = elm => eq(SugarElement.fromDom(rootElm), elm);
29409
      return closest$1(SugarElement.fromDom(elm), elm => getProperty(elm), isRoot);
29410
    };
29411
    const normalizeFontFamily = fontFamily => fontFamily.replace(/[\'\"\\]/g, '').replace(/,\s+/g, ',');
29412
    const getComputedFontProp = (propName, elm) => Optional.from(DOMUtils.DOM.getStyle(elm, propName, true));
29413
    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('');
29414
    const getFontSize = getFontProp('font-size');
29415
    const getFontFamily = compose(normalizeFontFamily, getFontProp('font-family'));
29416
 
29417
    const findFirstCaretElement = editor => firstPositionIn(editor.getBody()).bind(caret => {
29418
      const container = caret.container();
29419
      return Optional.from(isText$a(container) ? container.parentNode : container);
29420
    });
29421
    const getCaretElement = editor => Optional.from(editor.selection.getRng()).bind(rng => {
29422
      const root = editor.getBody();
29423
      const atStartOfNode = rng.startContainer === root && rng.startOffset === 0;
29424
      return atStartOfNode ? Optional.none() : Optional.from(editor.selection.getStart(true));
29425
    });
29426
    const bindRange = (editor, binder) => getCaretElement(editor).orThunk(curry(findFirstCaretElement, editor)).map(SugarElement.fromDom).filter(isElement$7).bind(binder);
29427
    const mapRange = (editor, mapper) => bindRange(editor, compose1(Optional.some, mapper));
29428
 
29429
    const fromFontSizeNumber = (editor, value) => {
29430
      if (/^[0-9.]+$/.test(value)) {
29431
        const fontSizeNumber = parseInt(value, 10);
29432
        if (fontSizeNumber >= 1 && fontSizeNumber <= 7) {
29433
          const fontSizes = getFontStyleValues(editor);
29434
          const fontClasses = getFontSizeClasses(editor);
29435
          if (fontClasses.length > 0) {
29436
            return fontClasses[fontSizeNumber - 1] || value;
29437
          } else {
29438
            return fontSizes[fontSizeNumber - 1] || value;
29439
          }
29440
        } else {
29441
          return value;
29442
        }
29443
      } else {
29444
        return value;
29445
      }
29446
    };
29447
    const normalizeFontNames = font => {
29448
      const fonts = font.split(/\s*,\s*/);
29449
      return map$3(fonts, font => {
29450
        if (font.indexOf(' ') !== -1 && !(startsWith(font, '"') || startsWith(font, `'`))) {
29451
          return `'${ font }'`;
29452
        } else {
29453
          return font;
29454
        }
29455
      }).join(',');
29456
    };
29457
    const fontNameAction = (editor, value) => {
29458
      const font = fromFontSizeNumber(editor, value);
29459
      editor.formatter.toggle('fontname', { value: normalizeFontNames(font) });
29460
      editor.nodeChanged();
29461
    };
29462
    const fontNameQuery = editor => mapRange(editor, elm => getFontFamily(editor.getBody(), elm.dom)).getOr('');
29463
    const fontSizeAction = (editor, value) => {
29464
      editor.formatter.toggle('fontsize', { value: fromFontSizeNumber(editor, value) });
29465
      editor.nodeChanged();
29466
    };
29467
    const fontSizeQuery = editor => mapRange(editor, elm => getFontSize(editor.getBody(), elm.dom)).getOr('');
29468
 
29469
    const lineHeightQuery = editor => mapRange(editor, elm => {
29470
      const root = SugarElement.fromDom(editor.getBody());
29471
      const specifiedStyle = closest$1(elm, elm => getRaw(elm, 'line-height'), curry(eq, root));
29472
      const computedStyle = () => {
29473
        const lineHeight = parseFloat(get$7(elm, 'line-height'));
29474
        const fontSize = parseFloat(get$7(elm, 'font-size'));
29475
        return String(lineHeight / fontSize);
29476
      };
29477
      return specifiedStyle.getOrThunk(computedStyle);
29478
    }).getOr('');
29479
    const lineHeightAction = (editor, lineHeight) => {
29480
      editor.formatter.toggle('lineheight', { value: String(lineHeight) });
29481
      editor.nodeChanged();
29482
    };
29483
 
29484
    const registerExecCommands$2 = editor => {
29485
      const toggleFormat = (name, value) => {
29486
        editor.formatter.toggle(name, value);
29487
        editor.nodeChanged();
29488
      };
29489
      editor.editorCommands.addCommands({
29490
        'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': command => {
29491
          toggleFormat(command);
29492
        },
29493
        'ForeColor,HiliteColor': (command, _ui, value) => {
29494
          toggleFormat(command, { value });
29495
        },
29496
        'BackColor': (_command, _ui, value) => {
29497
          toggleFormat('hilitecolor', { value });
29498
        },
29499
        'FontName': (_command, _ui, value) => {
29500
          fontNameAction(editor, value);
29501
        },
29502
        'FontSize': (_command, _ui, value) => {
29503
          fontSizeAction(editor, value);
29504
        },
29505
        'LineHeight': (_command, _ui, value) => {
29506
          lineHeightAction(editor, value);
29507
        },
29508
        'Lang': (command, _ui, lang) => {
29509
          var _a;
29510
          toggleFormat(command, {
29511
            value: lang.code,
29512
            customValue: (_a = lang.customCode) !== null && _a !== void 0 ? _a : null
29513
          });
29514
        },
29515
        'RemoveFormat': command => {
29516
          editor.formatter.remove(command);
29517
        },
29518
        'mceBlockQuote': () => {
29519
          toggleFormat('blockquote');
29520
        },
29521
        'FormatBlock': (_command, _ui, value) => {
29522
          toggleFormat(isString(value) ? value : 'p');
29523
        },
29524
        'mceToggleFormat': (_command, _ui, value) => {
29525
          toggleFormat(value);
29526
        }
29527
      });
29528
    };
29529
    const registerQueryValueCommands = editor => {
29530
      const isFormatMatch = name => editor.formatter.match(name);
29531
      editor.editorCommands.addCommands({
29532
        'Bold,Italic,Underline,Strikethrough,Superscript,Subscript': command => isFormatMatch(command),
29533
        'mceBlockQuote': () => isFormatMatch('blockquote')
29534
      }, 'state');
29535
      editor.editorCommands.addQueryValueHandler('FontName', () => fontNameQuery(editor));
29536
      editor.editorCommands.addQueryValueHandler('FontSize', () => fontSizeQuery(editor));
29537
      editor.editorCommands.addQueryValueHandler('LineHeight', () => lineHeightQuery(editor));
29538
    };
29539
    const registerCommands$8 = editor => {
29540
      registerExecCommands$2(editor);
29541
      registerQueryValueCommands(editor);
29542
    };
29543
 
29544
    const registerCommands$7 = editor => {
29545
      editor.editorCommands.addCommands({
29546
        mceAddUndoLevel: () => {
29547
          editor.undoManager.add();
29548
        },
29549
        mceEndUndoLevel: () => {
29550
          editor.undoManager.add();
29551
        },
29552
        Undo: () => {
29553
          editor.undoManager.undo();
29554
        },
29555
        Redo: () => {
29556
          editor.undoManager.redo();
29557
        }
29558
      });
29559
    };
29560
 
29561
    const registerCommands$6 = editor => {
29562
      editor.editorCommands.addCommands({
29563
        Indent: () => {
29564
          indent(editor);
29565
        },
29566
        Outdent: () => {
29567
          outdent(editor);
29568
        }
29569
      });
29570
      editor.editorCommands.addCommands({ Outdent: () => canOutdent(editor) }, 'state');
29571
    };
29572
 
29573
    const registerCommands$5 = editor => {
29574
      const applyLinkToSelection = (_command, _ui, value) => {
29575
        const linkDetails = isString(value) ? { href: value } : value;
29576
        const anchor = editor.dom.getParent(editor.selection.getNode(), 'a');
29577
        if (isObject(linkDetails) && isString(linkDetails.href)) {
29578
          linkDetails.href = linkDetails.href.replace(/ /g, '%20');
29579
          if (!anchor || !linkDetails.href) {
29580
            editor.formatter.remove('link');
29581
          }
29582
          if (linkDetails.href) {
29583
            editor.formatter.apply('link', linkDetails, anchor);
29584
          }
29585
        }
29586
      };
29587
      editor.editorCommands.addCommands({
29588
        unlink: () => {
29589
          if (editor.selection.isEditable()) {
29590
            if (editor.selection.isCollapsed()) {
29591
              const elm = editor.dom.getParent(editor.selection.getStart(), 'a');
29592
              if (elm) {
29593
                editor.dom.remove(elm, true);
29594
              }
29595
              return;
29596
            }
29597
            editor.formatter.remove('link');
29598
          }
29599
        },
29600
        mceInsertLink: applyLinkToSelection,
29601
        createLink: applyLinkToSelection
29602
      });
29603
    };
29604
 
29605
    const registerExecCommands$1 = editor => {
29606
      editor.editorCommands.addCommands({
29607
        'InsertUnorderedList,InsertOrderedList': command => {
29608
          editor.getDoc().execCommand(command);
29609
          const listElm = editor.dom.getParent(editor.selection.getNode(), 'ol,ul');
29610
          if (listElm) {
29611
            const listParent = listElm.parentNode;
29612
            if (listParent && /^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) {
29613
              const bm = editor.selection.getBookmark();
29614
              editor.dom.split(listParent, listElm);
29615
              editor.selection.moveToBookmark(bm);
29616
            }
29617
          }
29618
        }
29619
      });
29620
    };
29621
    const registerQueryStateCommands = editor => {
29622
      editor.editorCommands.addCommands({
29623
        'InsertUnorderedList,InsertOrderedList': command => {
29624
          const list = editor.dom.getParent(editor.selection.getNode(), 'ul,ol');
29625
          return list && (command === 'insertunorderedlist' && list.tagName === 'UL' || command === 'insertorderedlist' && list.tagName === 'OL');
29626
        }
29627
      }, 'state');
29628
    };
29629
    const registerCommands$4 = editor => {
29630
      registerExecCommands$1(editor);
29631
      registerQueryStateCommands(editor);
29632
    };
29633
 
29634
    const getTopParentBlock = (editor, node, root, container) => {
29635
      const dom = editor.dom;
29636
      const selector = node => dom.isBlock(node) && node.parentElement === root;
29637
      const topParentBlock = selector(node) ? node : dom.getParent(container, selector, root);
29638
      return Optional.from(topParentBlock).map(SugarElement.fromDom);
29639
    };
29640
    const insert = (editor, before) => {
29641
      const dom = editor.dom;
29642
      const rng = editor.selection.getRng();
29643
      const node = before ? editor.selection.getStart() : editor.selection.getEnd();
29644
      const container = before ? rng.startContainer : rng.endContainer;
29645
      const root = getEditableRoot(dom, container);
29646
      if (!root || !root.isContentEditable) {
29647
        return;
29648
      }
29649
      const insertFn = before ? before$3 : after$4;
29650
      const newBlockName = getForcedRootBlock(editor);
29651
      getTopParentBlock(editor, node, root, container).each(parentBlock => {
29652
        const newBlock = createNewBlock(editor, container, parentBlock.dom, root, false, newBlockName);
29653
        insertFn(parentBlock, SugarElement.fromDom(newBlock));
29654
        editor.selection.setCursorLocation(newBlock, 0);
29655
        editor.dispatch('NewBlock', { newBlock });
29656
        fireInputEvent(editor, 'insertParagraph');
29657
      });
29658
    };
29659
    const insertBefore = editor => insert(editor, true);
29660
    const insertAfter = editor => insert(editor, false);
29661
 
29662
    const registerCommands$3 = editor => {
29663
      editor.editorCommands.addCommands({
29664
        InsertNewBlockBefore: () => {
29665
          insertBefore(editor);
29666
        },
29667
        InsertNewBlockAfter: () => {
29668
          insertAfter(editor);
29669
        }
29670
      });
29671
    };
29672
 
29673
    const registerCommands$2 = editor => {
29674
      editor.editorCommands.addCommands({
29675
        insertParagraph: () => {
29676
          insertBreak(blockbreak, editor);
29677
        },
29678
        mceInsertNewLine: (_command, _ui, value) => {
29679
          insert$1(editor, value);
29680
        },
29681
        InsertLineBreak: (_command, _ui, _value) => {
29682
          insertBreak(linebreak, editor);
29683
        }
29684
      });
29685
    };
29686
 
29687
    const registerCommands$1 = editor => {
29688
      editor.editorCommands.addCommands({
29689
        mceSelectNodeDepth: (_command, _ui, value) => {
29690
          let counter = 0;
29691
          editor.dom.getParent(editor.selection.getNode(), node => {
29692
            if (isElement$6(node) && counter++ === value) {
29693
              editor.selection.select(node);
29694
              return false;
29695
            } else {
29696
              return true;
29697
            }
29698
          }, editor.getBody());
29699
        },
29700
        mceSelectNode: (_command, _ui, value) => {
29701
          editor.selection.select(value);
29702
        },
29703
        selectAll: () => {
29704
          const editingHost = editor.dom.getParent(editor.selection.getStart(), isContentEditableTrue$3);
29705
          if (editingHost) {
29706
            const rng = editor.dom.createRng();
29707
            rng.selectNodeContents(editingHost);
29708
            editor.selection.setRng(rng);
29709
          }
29710
        }
29711
      });
29712
    };
29713
 
29714
    const registerExecCommands = editor => {
29715
      editor.editorCommands.addCommands({
29716
        mceRemoveNode: (_command, _ui, value) => {
29717
          const node = value !== null && value !== void 0 ? value : editor.selection.getNode();
29718
          if (node !== editor.getBody()) {
29719
            const bm = editor.selection.getBookmark();
29720
            editor.dom.remove(node, true);
29721
            editor.selection.moveToBookmark(bm);
29722
          }
29723
        },
29724
        mcePrint: () => {
29725
          editor.getWin().print();
29726
        },
29727
        mceFocus: (_command, _ui, value) => {
29728
          focus(editor, value === true);
29729
        },
29730
        mceToggleVisualAid: () => {
29731
          editor.hasVisual = !editor.hasVisual;
29732
          editor.addVisual();
29733
        }
29734
      });
29735
    };
29736
    const registerCommands = editor => {
29737
      registerCommands$b(editor);
29738
      registerCommands$a(editor);
29739
      registerCommands$7(editor);
29740
      registerCommands$1(editor);
29741
      registerCommands$9(editor);
29742
      registerCommands$5(editor);
29743
      registerCommands$6(editor);
29744
      registerCommands$3(editor);
29745
      registerCommands$2(editor);
29746
      registerCommands$4(editor);
29747
      registerCommands$8(editor);
29748
      registerExecCommands(editor);
29749
    };
29750
 
29751
    const selectionSafeCommands = ['toggleview'];
29752
    const isSelectionSafeCommand = command => contains$2(selectionSafeCommands, command.toLowerCase());
29753
    class EditorCommands {
29754
      constructor(editor) {
29755
        this.commands = {
29756
          state: {},
29757
          exec: {},
29758
          value: {}
29759
        };
29760
        this.editor = editor;
29761
      }
29762
      execCommand(command, ui = false, value, args) {
29763
        const editor = this.editor;
29764
        const lowerCaseCommand = command.toLowerCase();
29765
        const skipFocus = args === null || args === void 0 ? void 0 : args.skip_focus;
29766
        if (editor.removed) {
29767
          return false;
29768
        }
29769
        if (lowerCaseCommand !== 'mcefocus') {
29770
          if (!/^(mceAddUndoLevel|mceEndUndoLevel)$/i.test(lowerCaseCommand) && !skipFocus) {
29771
            editor.focus();
29772
          } else {
29773
            restore(editor);
29774
          }
29775
        }
29776
        const eventArgs = editor.dispatch('BeforeExecCommand', {
29777
          command,
29778
          ui,
29779
          value
29780
        });
29781
        if (eventArgs.isDefaultPrevented()) {
29782
          return false;
29783
        }
29784
        const func = this.commands.exec[lowerCaseCommand];
29785
        if (isFunction(func)) {
29786
          func(lowerCaseCommand, ui, value);
29787
          editor.dispatch('ExecCommand', {
29788
            command,
29789
            ui,
29790
            value
29791
          });
29792
          return true;
29793
        }
29794
        return false;
29795
      }
29796
      queryCommandState(command) {
29797
        if (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden() || this.editor.removed) {
29798
          return false;
29799
        }
29800
        const lowerCaseCommand = command.toLowerCase();
29801
        const func = this.commands.state[lowerCaseCommand];
29802
        if (isFunction(func)) {
29803
          return func(lowerCaseCommand);
29804
        }
29805
        return false;
29806
      }
29807
      queryCommandValue(command) {
29808
        if (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden() || this.editor.removed) {
29809
          return '';
29810
        }
29811
        const lowerCaseCommand = command.toLowerCase();
29812
        const func = this.commands.value[lowerCaseCommand];
29813
        if (isFunction(func)) {
29814
          return func(lowerCaseCommand);
29815
        }
29816
        return '';
29817
      }
29818
      addCommands(commandList, type = 'exec') {
29819
        const commands = this.commands;
29820
        each$d(commandList, (callback, command) => {
29821
          each$e(command.toLowerCase().split(','), command => {
29822
            commands[type][command] = callback;
29823
          });
29824
        });
29825
      }
29826
      addCommand(command, callback, scope) {
29827
        const lowerCaseCommand = command.toLowerCase();
29828
        this.commands.exec[lowerCaseCommand] = (_command, ui, value) => callback.call(scope !== null && scope !== void 0 ? scope : this.editor, ui, value);
29829
      }
29830
      queryCommandSupported(command) {
29831
        const lowerCaseCommand = command.toLowerCase();
29832
        if (this.commands.exec[lowerCaseCommand]) {
29833
          return true;
29834
        } else {
29835
          return false;
29836
        }
29837
      }
29838
      addQueryStateHandler(command, callback, scope) {
29839
        this.commands.state[command.toLowerCase()] = () => callback.call(scope !== null && scope !== void 0 ? scope : this.editor);
29840
      }
29841
      addQueryValueHandler(command, callback, scope) {
29842
        this.commands.value[command.toLowerCase()] = () => callback.call(scope !== null && scope !== void 0 ? scope : this.editor);
29843
      }
29844
    }
29845
 
29846
    const internalContentEditableAttr = 'data-mce-contenteditable';
29847
    const toggleClass = (elm, cls, state) => {
29848
      if (has(elm, cls) && !state) {
29849
        remove$7(elm, cls);
29850
      } else if (state) {
29851
        add$2(elm, cls);
29852
      }
29853
    };
29854
    const setEditorCommandState = (editor, cmd, state) => {
29855
      try {
29856
        editor.getDoc().execCommand(cmd, false, String(state));
29857
      } catch (ex) {
29858
      }
29859
    };
29860
    const setContentEditable = (elm, state) => {
29861
      elm.dom.contentEditable = state ? 'true' : 'false';
29862
    };
29863
    const switchOffContentEditableTrue = elm => {
29864
      each$e(descendants(elm, '*[contenteditable="true"]'), elm => {
29865
        set$3(elm, internalContentEditableAttr, 'true');
29866
        setContentEditable(elm, false);
29867
      });
29868
    };
29869
    const switchOnContentEditableTrue = elm => {
29870
      each$e(descendants(elm, `*[${ internalContentEditableAttr }="true"]`), elm => {
29871
        remove$a(elm, internalContentEditableAttr);
29872
        setContentEditable(elm, true);
29873
      });
29874
    };
29875
    const removeFakeSelection = editor => {
29876
      Optional.from(editor.selection.getNode()).each(elm => {
29877
        elm.removeAttribute('data-mce-selected');
29878
      });
29879
    };
29880
    const restoreFakeSelection = editor => {
29881
      editor.selection.setRng(editor.selection.getRng());
29882
    };
29883
    const toggleReadOnly = (editor, state) => {
29884
      const body = SugarElement.fromDom(editor.getBody());
29885
      toggleClass(body, 'mce-content-readonly', state);
29886
      if (state) {
29887
        editor.selection.controlSelection.hideResizeRect();
29888
        editor._selectionOverrides.hideFakeCaret();
29889
        removeFakeSelection(editor);
29890
        editor.readonly = true;
29891
        setContentEditable(body, false);
29892
        switchOffContentEditableTrue(body);
29893
      } else {
29894
        editor.readonly = false;
29895
        if (editor.hasEditableRoot()) {
29896
          setContentEditable(body, true);
29897
        }
29898
        switchOnContentEditableTrue(body);
29899
        setEditorCommandState(editor, 'StyleWithCSS', false);
29900
        setEditorCommandState(editor, 'enableInlineTableEditing', false);
29901
        setEditorCommandState(editor, 'enableObjectResizing', false);
29902
        if (hasEditorOrUiFocus(editor)) {
29903
          editor.focus();
29904
        }
29905
        restoreFakeSelection(editor);
29906
        editor.nodeChanged();
29907
      }
29908
    };
29909
    const isReadOnly = editor => editor.readonly;
29910
    const registerFilters = editor => {
29911
      editor.parser.addAttributeFilter('contenteditable', nodes => {
29912
        if (isReadOnly(editor)) {
29913
          each$e(nodes, node => {
29914
            node.attr(internalContentEditableAttr, node.attr('contenteditable'));
29915
            node.attr('contenteditable', 'false');
29916
          });
29917
        }
29918
      });
29919
      editor.serializer.addAttributeFilter(internalContentEditableAttr, nodes => {
29920
        if (isReadOnly(editor)) {
29921
          each$e(nodes, node => {
29922
            node.attr('contenteditable', node.attr(internalContentEditableAttr));
29923
          });
29924
        }
29925
      });
29926
      editor.serializer.addTempAttr(internalContentEditableAttr);
29927
    };
29928
    const registerReadOnlyContentFilters = editor => {
29929
      if (editor.serializer) {
29930
        registerFilters(editor);
29931
      } else {
29932
        editor.on('PreInit', () => {
29933
          registerFilters(editor);
29934
        });
29935
      }
29936
    };
29937
    const isClickEvent = e => e.type === 'click';
29938
    const allowedEvents = ['copy'];
29939
    const isReadOnlyAllowedEvent = e => contains$2(allowedEvents, e.type);
29940
    const getAnchorHrefOpt = (editor, elm) => {
29941
      const isRoot = elm => eq(elm, SugarElement.fromDom(editor.getBody()));
29942
      return closest$3(elm, 'a', isRoot).bind(a => getOpt(a, 'href'));
29943
    };
29944
    const processReadonlyEvents = (editor, e) => {
29945
      if (isClickEvent(e) && !VK.metaKeyPressed(e)) {
29946
        const elm = SugarElement.fromDom(e.target);
29947
        getAnchorHrefOpt(editor, elm).each(href => {
29948
          e.preventDefault();
29949
          if (/^#/.test(href)) {
29950
            const targetEl = editor.dom.select(`${ href },[name="${ removeLeading(href, '#') }"]`);
29951
            if (targetEl.length) {
29952
              editor.selection.scrollIntoView(targetEl[0], true);
29953
            }
29954
          } else {
29955
            window.open(href, '_blank', 'rel=noopener noreferrer,menubar=yes,toolbar=yes,location=yes,status=yes,resizable=yes,scrollbars=yes');
29956
          }
29957
        });
29958
      } else if (isReadOnlyAllowedEvent(e)) {
29959
        editor.dispatch(e.type, e);
29960
      }
29961
    };
29962
    const registerReadOnlySelectionBlockers = editor => {
29963
      editor.on('ShowCaret', e => {
29964
        if (isReadOnly(editor)) {
29965
          e.preventDefault();
29966
        }
29967
      });
29968
      editor.on('ObjectSelected', e => {
29969
        if (isReadOnly(editor)) {
29970
          e.preventDefault();
29971
        }
29972
      });
29973
    };
29974
 
29975
    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', ' ');
29976
    class EventDispatcher {
29977
      static isNative(name) {
29978
        return !!nativeEvents[name.toLowerCase()];
29979
      }
29980
      constructor(settings) {
29981
        this.bindings = {};
29982
        this.settings = settings || {};
29983
        this.scope = this.settings.scope || this;
29984
        this.toggleEvent = this.settings.toggleEvent || never;
29985
      }
29986
      fire(name, args) {
29987
        return this.dispatch(name, args);
29988
      }
29989
      dispatch(name, args) {
29990
        const lcName = name.toLowerCase();
29991
        const event = normalize$3(lcName, args !== null && args !== void 0 ? args : {}, this.scope);
29992
        if (this.settings.beforeFire) {
29993
          this.settings.beforeFire(event);
29994
        }
29995
        const handlers = this.bindings[lcName];
29996
        if (handlers) {
29997
          for (let i = 0, l = handlers.length; i < l; i++) {
29998
            const callback = handlers[i];
29999
            if (callback.removed) {
30000
              continue;
30001
            }
30002
            if (callback.once) {
30003
              this.off(lcName, callback.func);
30004
            }
30005
            if (event.isImmediatePropagationStopped()) {
30006
              return event;
30007
            }
30008
            if (callback.func.call(this.scope, event) === false) {
30009
              event.preventDefault();
30010
              return event;
30011
            }
30012
          }
30013
        }
30014
        return event;
30015
      }
30016
      on(name, callback, prepend, extra) {
30017
        if (callback === false) {
30018
          callback = never;
30019
        }
30020
        if (callback) {
30021
          const wrappedCallback = {
30022
            func: callback,
30023
            removed: false
30024
          };
30025
          if (extra) {
30026
            Tools.extend(wrappedCallback, extra);
30027
          }
30028
          const names = name.toLowerCase().split(' ');
30029
          let i = names.length;
30030
          while (i--) {
30031
            const currentName = names[i];
30032
            let handlers = this.bindings[currentName];
30033
            if (!handlers) {
30034
              handlers = [];
30035
              this.toggleEvent(currentName, true);
30036
            }
30037
            if (prepend) {
30038
              handlers = [
30039
                wrappedCallback,
30040
                ...handlers
30041
              ];
30042
            } else {
30043
              handlers = [
30044
                ...handlers,
30045
                wrappedCallback
30046
              ];
30047
            }
30048
            this.bindings[currentName] = handlers;
30049
          }
30050
        }
30051
        return this;
30052
      }
30053
      off(name, callback) {
30054
        if (name) {
30055
          const names = name.toLowerCase().split(' ');
30056
          let i = names.length;
30057
          while (i--) {
30058
            const currentName = names[i];
30059
            let handlers = this.bindings[currentName];
30060
            if (!currentName) {
30061
              each$d(this.bindings, (_value, bindingName) => {
30062
                this.toggleEvent(bindingName, false);
30063
                delete this.bindings[bindingName];
30064
              });
30065
              return this;
30066
            }
30067
            if (handlers) {
30068
              if (!callback) {
30069
                handlers.length = 0;
30070
              } else {
30071
                const filteredHandlers = partition$2(handlers, handler => handler.func === callback);
30072
                handlers = filteredHandlers.fail;
30073
                this.bindings[currentName] = handlers;
30074
                each$e(filteredHandlers.pass, handler => {
30075
                  handler.removed = true;
30076
                });
30077
              }
30078
              if (!handlers.length) {
30079
                this.toggleEvent(name, false);
30080
                delete this.bindings[currentName];
30081
              }
30082
            }
30083
          }
30084
        } else {
30085
          each$d(this.bindings, (_value, name) => {
30086
            this.toggleEvent(name, false);
30087
          });
30088
          this.bindings = {};
30089
        }
30090
        return this;
30091
      }
30092
      once(name, callback, prepend) {
30093
        return this.on(name, callback, prepend, { once: true });
30094
      }
30095
      has(name) {
30096
        name = name.toLowerCase();
30097
        const binding = this.bindings[name];
30098
        return !(!binding || binding.length === 0);
30099
      }
30100
    }
30101
 
30102
    const getEventDispatcher = obj => {
30103
      if (!obj._eventDispatcher) {
30104
        obj._eventDispatcher = new EventDispatcher({
30105
          scope: obj,
30106
          toggleEvent: (name, state) => {
30107
            if (EventDispatcher.isNative(name) && obj.toggleNativeEvent) {
30108
              obj.toggleNativeEvent(name, state);
30109
            }
30110
          }
30111
        });
30112
      }
30113
      return obj._eventDispatcher;
30114
    };
30115
    const Observable = {
30116
      fire(name, args, bubble) {
30117
        return this.dispatch(name, args, bubble);
30118
      },
30119
      dispatch(name, args, bubble) {
30120
        const self = this;
30121
        if (self.removed && name !== 'remove' && name !== 'detach') {
30122
          return normalize$3(name.toLowerCase(), args !== null && args !== void 0 ? args : {}, self);
30123
        }
30124
        const dispatcherArgs = getEventDispatcher(self).dispatch(name, args);
30125
        if (bubble !== false && self.parent) {
30126
          let parent = self.parent();
30127
          while (parent && !dispatcherArgs.isPropagationStopped()) {
30128
            parent.dispatch(name, dispatcherArgs, false);
30129
            parent = parent.parent ? parent.parent() : undefined;
30130
          }
30131
        }
30132
        return dispatcherArgs;
30133
      },
30134
      on(name, callback, prepend) {
30135
        return getEventDispatcher(this).on(name, callback, prepend);
30136
      },
30137
      off(name, callback) {
30138
        return getEventDispatcher(this).off(name, callback);
30139
      },
30140
      once(name, callback) {
30141
        return getEventDispatcher(this).once(name, callback);
30142
      },
30143
      hasEventListeners(name) {
30144
        return getEventDispatcher(this).has(name);
30145
      }
30146
    };
30147
 
30148
    const DOM$2 = DOMUtils.DOM;
30149
    let customEventRootDelegates;
30150
    const getEventTarget = (editor, eventName) => {
30151
      if (eventName === 'selectionchange') {
30152
        return editor.getDoc();
30153
      }
30154
      if (!editor.inline && /^(?:mouse|touch|click|contextmenu|drop|dragover|dragend)/.test(eventName)) {
30155
        return editor.getDoc().documentElement;
30156
      }
30157
      const eventRoot = getEventRoot(editor);
30158
      if (eventRoot) {
30159
        if (!editor.eventRoot) {
30160
          editor.eventRoot = DOM$2.select(eventRoot)[0];
30161
        }
30162
        return editor.eventRoot;
30163
      }
30164
      return editor.getBody();
30165
    };
30166
    const isListening = editor => !editor.hidden && !isReadOnly(editor);
30167
    const fireEvent = (editor, eventName, e) => {
30168
      if (isListening(editor)) {
30169
        editor.dispatch(eventName, e);
30170
      } else if (isReadOnly(editor)) {
30171
        processReadonlyEvents(editor, e);
30172
      }
30173
    };
30174
    const bindEventDelegate = (editor, eventName) => {
30175
      if (!editor.delegates) {
30176
        editor.delegates = {};
30177
      }
30178
      if (editor.delegates[eventName] || editor.removed) {
30179
        return;
30180
      }
30181
      const eventRootElm = getEventTarget(editor, eventName);
30182
      if (getEventRoot(editor)) {
30183
        if (!customEventRootDelegates) {
30184
          customEventRootDelegates = {};
30185
          editor.editorManager.on('removeEditor', () => {
30186
            if (!editor.editorManager.activeEditor) {
30187
              if (customEventRootDelegates) {
30188
                each$d(customEventRootDelegates, (_value, name) => {
30189
                  editor.dom.unbind(getEventTarget(editor, name));
30190
                });
30191
                customEventRootDelegates = null;
30192
              }
30193
            }
30194
          });
30195
        }
30196
        if (customEventRootDelegates[eventName]) {
30197
          return;
30198
        }
30199
        const delegate = e => {
30200
          const target = e.target;
30201
          const editors = editor.editorManager.get();
30202
          let i = editors.length;
30203
          while (i--) {
30204
            const body = editors[i].getBody();
30205
            if (body === target || DOM$2.isChildOf(target, body)) {
30206
              fireEvent(editors[i], eventName, e);
30207
            }
30208
          }
30209
        };
30210
        customEventRootDelegates[eventName] = delegate;
30211
        DOM$2.bind(eventRootElm, eventName, delegate);
30212
      } else {
30213
        const delegate = e => {
30214
          fireEvent(editor, eventName, e);
30215
        };
30216
        DOM$2.bind(eventRootElm, eventName, delegate);
30217
        editor.delegates[eventName] = delegate;
30218
      }
30219
    };
30220
    const EditorObservable = {
30221
      ...Observable,
30222
      bindPendingEventDelegates() {
30223
        const self = this;
30224
        Tools.each(self._pendingNativeEvents, name => {
30225
          bindEventDelegate(self, name);
30226
        });
30227
      },
30228
      toggleNativeEvent(name, state) {
30229
        const self = this;
30230
        if (name === 'focus' || name === 'blur') {
30231
          return;
30232
        }
30233
        if (self.removed) {
30234
          return;
30235
        }
30236
        if (state) {
30237
          if (self.initialized) {
30238
            bindEventDelegate(self, name);
30239
          } else {
30240
            if (!self._pendingNativeEvents) {
30241
              self._pendingNativeEvents = [name];
30242
            } else {
30243
              self._pendingNativeEvents.push(name);
30244
            }
30245
          }
30246
        } else if (self.initialized && self.delegates) {
30247
          self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
30248
          delete self.delegates[name];
30249
        }
30250
      },
30251
      unbindAllNativeEvents() {
30252
        const self = this;
30253
        const body = self.getBody();
30254
        const dom = self.dom;
30255
        if (self.delegates) {
30256
          each$d(self.delegates, (value, name) => {
30257
            self.dom.unbind(getEventTarget(self, name), name, value);
30258
          });
30259
          delete self.delegates;
30260
        }
30261
        if (!self.inline && body && dom) {
30262
          body.onload = null;
30263
          dom.unbind(self.getWin());
30264
          dom.unbind(self.getDoc());
30265
        }
30266
        if (dom) {
30267
          dom.unbind(body);
30268
          dom.unbind(self.getContainer());
30269
        }
30270
      }
30271
    };
30272
 
30273
    const stringListProcessor = value => {
30274
      if (isString(value)) {
30275
        return {
30276
          value: value.split(/[ ,]/),
30277
          valid: true
30278
        };
30279
      } else if (isArrayOf(value, isString)) {
30280
        return {
30281
          value,
30282
          valid: true
30283
        };
30284
      } else {
30285
        return {
30286
          valid: false,
30287
          message: `The value must be a string[] or a comma/space separated string.`
30288
        };
30289
      }
30290
    };
30291
    const getBuiltInProcessor = type => {
30292
      const validator = (() => {
30293
        switch (type) {
30294
        case 'array':
30295
          return isArray$1;
30296
        case 'boolean':
30297
          return isBoolean;
30298
        case 'function':
30299
          return isFunction;
30300
        case 'number':
30301
          return isNumber;
30302
        case 'object':
30303
          return isObject;
30304
        case 'string':
30305
          return isString;
30306
        case 'string[]':
30307
          return stringListProcessor;
30308
        case 'object[]':
30309
          return val => isArrayOf(val, isObject);
30310
        case 'regexp':
30311
          return val => is$4(val, RegExp);
30312
        default:
30313
          return always;
30314
        }
30315
      })();
30316
      return value => processValue(value, validator, `The value must be a ${ type }.`);
30317
    };
30318
    const isBuiltInSpec = spec => isString(spec.processor);
30319
    const getErrorMessage = (message, result) => {
30320
      const additionalText = isEmpty$3(result.message) ? '' : `. ${ result.message }`;
30321
      return message + additionalText;
30322
    };
30323
    const isValidResult = result => result.valid;
30324
    const processValue = (value, processor, message = '') => {
30325
      const result = processor(value);
30326
      if (isBoolean(result)) {
30327
        return result ? {
30328
          value: value,
30329
          valid: true
30330
        } : {
30331
          valid: false,
30332
          message
30333
        };
30334
      } else {
30335
        return result;
30336
      }
30337
    };
30338
    const processDefaultValue = (name, defaultValue, processor) => {
30339
      if (!isUndefined(defaultValue)) {
30340
        const result = processValue(defaultValue, processor);
30341
        if (isValidResult(result)) {
30342
          return result.value;
30343
        } else {
30344
          console.error(getErrorMessage(`Invalid default value passed for the "${ name }" option`, result));
30345
        }
30346
      }
30347
      return undefined;
30348
    };
30349
    const create$5 = (editor, initialOptions) => {
30350
      const registry = {};
30351
      const values = {};
30352
      const setValue = (name, value, processor) => {
30353
        const result = processValue(value, processor);
30354
        if (isValidResult(result)) {
30355
          values[name] = result.value;
30356
          return true;
30357
        } else {
30358
          console.warn(getErrorMessage(`Invalid value passed for the ${ name } option`, result));
30359
          return false;
30360
        }
30361
      };
30362
      const register = (name, spec) => {
30363
        const processor = isBuiltInSpec(spec) ? getBuiltInProcessor(spec.processor) : spec.processor;
30364
        const defaultValue = processDefaultValue(name, spec.default, processor);
30365
        registry[name] = {
30366
          ...spec,
30367
          default: defaultValue,
30368
          processor
30369
        };
30370
        const initValue = get$a(values, name).orThunk(() => get$a(initialOptions, name));
30371
        initValue.each(value => setValue(name, value, processor));
30372
      };
30373
      const isRegistered = name => has$2(registry, name);
30374
      const get = name => get$a(values, name).orThunk(() => get$a(registry, name).map(spec => spec.default)).getOrUndefined();
30375
      const set = (name, value) => {
30376
        if (!isRegistered(name)) {
30377
          console.warn(`"${ name }" is not a registered option. Ensure the option has been registered before setting a value.`);
30378
          return false;
30379
        } else {
30380
          const spec = registry[name];
30381
          if (spec.immutable) {
30382
            console.error(`"${ name }" is an immutable option and cannot be updated`);
30383
            return false;
30384
          } else {
30385
            return setValue(name, value, spec.processor);
30386
          }
30387
        }
30388
      };
30389
      const unset = name => {
30390
        const registered = isRegistered(name);
30391
        if (registered) {
30392
          delete values[name];
30393
        }
30394
        return registered;
30395
      };
30396
      const isSet = name => has$2(values, name);
30397
      return {
30398
        register,
30399
        isRegistered,
30400
        get,
30401
        set,
30402
        unset,
30403
        isSet
30404
      };
30405
    };
30406
 
30407
    const defaultModes = [
30408
      'design',
30409
      'readonly'
30410
    ];
30411
    const switchToMode = (editor, activeMode, availableModes, mode) => {
30412
      const oldMode = availableModes[activeMode.get()];
30413
      const newMode = availableModes[mode];
30414
      try {
30415
        newMode.activate();
30416
      } catch (e) {
30417
        console.error(`problem while activating editor mode ${ mode }:`, e);
30418
        return;
30419
      }
30420
      oldMode.deactivate();
30421
      if (oldMode.editorReadOnly !== newMode.editorReadOnly) {
30422
        toggleReadOnly(editor, newMode.editorReadOnly);
30423
      }
30424
      activeMode.set(mode);
30425
      fireSwitchMode(editor, mode);
30426
    };
30427
    const setMode = (editor, availableModes, activeMode, mode) => {
30428
      if (mode === activeMode.get()) {
30429
        return;
30430
      } else if (!has$2(availableModes, mode)) {
30431
        throw new Error(`Editor mode '${ mode }' is invalid`);
30432
      }
30433
      if (editor.initialized) {
30434
        switchToMode(editor, activeMode, availableModes, mode);
30435
      } else {
30436
        editor.on('init', () => switchToMode(editor, activeMode, availableModes, mode));
30437
      }
30438
    };
30439
    const registerMode = (availableModes, mode, api) => {
30440
      if (contains$2(defaultModes, mode)) {
30441
        throw new Error(`Cannot override default mode ${ mode }`);
30442
      }
30443
      return {
30444
        ...availableModes,
30445
        [mode]: {
30446
          ...api,
30447
          deactivate: () => {
30448
            try {
30449
              api.deactivate();
30450
            } catch (e) {
30451
              console.error(`problem while deactivating editor mode ${ mode }:`, e);
30452
            }
30453
          }
30454
        }
30455
      };
30456
    };
30457
 
30458
    const create$4 = editor => {
30459
      const activeMode = Cell('design');
30460
      const availableModes = Cell({
30461
        design: {
30462
          activate: noop,
30463
          deactivate: noop,
30464
          editorReadOnly: false
30465
        },
30466
        readonly: {
30467
          activate: noop,
30468
          deactivate: noop,
30469
          editorReadOnly: true
30470
        }
30471
      });
30472
      registerReadOnlyContentFilters(editor);
30473
      registerReadOnlySelectionBlockers(editor);
30474
      return {
30475
        isReadOnly: () => isReadOnly(editor),
30476
        set: mode => setMode(editor, availableModes.get(), activeMode, mode),
30477
        get: () => activeMode.get(),
30478
        register: (mode, api) => {
30479
          availableModes.set(registerMode(availableModes.get(), mode, api));
30480
        }
30481
      };
30482
    };
30483
 
30484
    const each$2 = Tools.each, explode = Tools.explode;
30485
    const keyCodeLookup = {
30486
      f1: 112,
30487
      f2: 113,
30488
      f3: 114,
30489
      f4: 115,
30490
      f5: 116,
30491
      f6: 117,
30492
      f7: 118,
30493
      f8: 119,
30494
      f9: 120,
30495
      f10: 121,
30496
      f11: 122,
30497
      f12: 123
30498
    };
30499
    const modifierNames = Tools.makeMap('alt,ctrl,shift,meta,access');
30500
    const isModifier = key => key in modifierNames;
30501
    const parseShortcut = pattern => {
30502
      const shortcut = {};
30503
      const isMac = Env.os.isMacOS() || Env.os.isiOS();
30504
      each$2(explode(pattern.toLowerCase(), '+'), value => {
30505
        if (isModifier(value)) {
30506
          shortcut[value] = true;
30507
        } else {
30508
          if (/^[0-9]{2,}$/.test(value)) {
30509
            shortcut.keyCode = parseInt(value, 10);
30510
          } else {
30511
            shortcut.charCode = value.charCodeAt(0);
30512
            shortcut.keyCode = keyCodeLookup[value] || value.toUpperCase().charCodeAt(0);
30513
          }
30514
        }
30515
      });
30516
      const id = [shortcut.keyCode];
30517
      let key;
30518
      for (key in modifierNames) {
30519
        if (shortcut[key]) {
30520
          id.push(key);
30521
        } else {
30522
          shortcut[key] = false;
30523
        }
30524
      }
30525
      shortcut.id = id.join(',');
30526
      if (shortcut.access) {
30527
        shortcut.alt = true;
30528
        if (isMac) {
30529
          shortcut.ctrl = true;
30530
        } else {
30531
          shortcut.shift = true;
30532
        }
30533
      }
30534
      if (shortcut.meta) {
30535
        if (isMac) {
30536
          shortcut.meta = true;
30537
        } else {
30538
          shortcut.ctrl = true;
30539
          shortcut.meta = false;
30540
        }
30541
      }
30542
      return shortcut;
30543
    };
30544
    class Shortcuts {
30545
      constructor(editor) {
30546
        this.shortcuts = {};
30547
        this.pendingPatterns = [];
30548
        this.editor = editor;
30549
        const self = this;
30550
        editor.on('keyup keypress keydown', e => {
30551
          if ((self.hasModifier(e) || self.isFunctionKey(e)) && !e.isDefaultPrevented()) {
30552
            each$2(self.shortcuts, shortcut => {
30553
              if (self.matchShortcut(e, shortcut)) {
30554
                self.pendingPatterns = shortcut.subpatterns.slice(0);
30555
                if (e.type === 'keydown') {
30556
                  self.executeShortcutAction(shortcut);
30557
                }
30558
              }
30559
            });
30560
            if (self.matchShortcut(e, self.pendingPatterns[0])) {
30561
              if (self.pendingPatterns.length === 1) {
30562
                if (e.type === 'keydown') {
30563
                  self.executeShortcutAction(self.pendingPatterns[0]);
30564
                }
30565
              }
30566
              self.pendingPatterns.shift();
30567
            }
30568
          }
30569
        });
30570
      }
30571
      add(pattern, desc, cmdFunc, scope) {
30572
        const self = this;
30573
        const func = self.normalizeCommandFunc(cmdFunc);
30574
        each$2(explode(Tools.trim(pattern)), pattern => {
30575
          const shortcut = self.createShortcut(pattern, desc, func, scope);
30576
          self.shortcuts[shortcut.id] = shortcut;
30577
        });
30578
        return true;
30579
      }
30580
      remove(pattern) {
30581
        const shortcut = this.createShortcut(pattern);
30582
        if (this.shortcuts[shortcut.id]) {
30583
          delete this.shortcuts[shortcut.id];
30584
          return true;
30585
        }
30586
        return false;
30587
      }
30588
      normalizeCommandFunc(cmdFunc) {
30589
        const self = this;
30590
        const cmd = cmdFunc;
30591
        if (typeof cmd === 'string') {
30592
          return () => {
30593
            self.editor.execCommand(cmd, false, null);
30594
          };
30595
        } else if (Tools.isArray(cmd)) {
30596
          return () => {
30597
            self.editor.execCommand(cmd[0], cmd[1], cmd[2]);
30598
          };
30599
        } else {
30600
          return cmd;
30601
        }
30602
      }
30603
      createShortcut(pattern, desc, cmdFunc, scope) {
30604
        const shortcuts = Tools.map(explode(pattern, '>'), parseShortcut);
30605
        shortcuts[shortcuts.length - 1] = Tools.extend(shortcuts[shortcuts.length - 1], {
30606
          func: cmdFunc,
30607
          scope: scope || this.editor
30608
        });
30609
        return Tools.extend(shortcuts[0], {
30610
          desc: this.editor.translate(desc),
30611
          subpatterns: shortcuts.slice(1)
30612
        });
30613
      }
30614
      hasModifier(e) {
30615
        return e.altKey || e.ctrlKey || e.metaKey;
30616
      }
30617
      isFunctionKey(e) {
30618
        return e.type === 'keydown' && e.keyCode >= 112 && e.keyCode <= 123;
30619
      }
30620
      matchShortcut(e, shortcut) {
30621
        if (!shortcut) {
30622
          return false;
30623
        }
30624
        if (shortcut.ctrl !== e.ctrlKey || shortcut.meta !== e.metaKey) {
30625
          return false;
30626
        }
30627
        if (shortcut.alt !== e.altKey || shortcut.shift !== e.shiftKey) {
30628
          return false;
30629
        }
30630
        if (e.keyCode === shortcut.keyCode || e.charCode && e.charCode === shortcut.charCode) {
30631
          e.preventDefault();
30632
          return true;
30633
        }
30634
        return false;
30635
      }
30636
      executeShortcutAction(shortcut) {
30637
        return shortcut.func ? shortcut.func.call(shortcut.scope) : null;
30638
      }
30639
    }
30640
 
30641
    const create$3 = () => {
30642
      const buttons = {};
30643
      const menuItems = {};
30644
      const popups = {};
30645
      const icons = {};
30646
      const contextMenus = {};
30647
      const contextToolbars = {};
30648
      const sidebars = {};
30649
      const views = {};
30650
      const add = (collection, type) => (name, spec) => {
30651
        collection[name.toLowerCase()] = {
30652
          ...spec,
30653
          type
30654
        };
30655
      };
30656
      const addIcon = (name, svgData) => icons[name.toLowerCase()] = svgData;
30657
      return {
30658
        addButton: add(buttons, 'button'),
30659
        addGroupToolbarButton: add(buttons, 'grouptoolbarbutton'),
30660
        addToggleButton: add(buttons, 'togglebutton'),
30661
        addMenuButton: add(buttons, 'menubutton'),
30662
        addSplitButton: add(buttons, 'splitbutton'),
30663
        addMenuItem: add(menuItems, 'menuitem'),
30664
        addNestedMenuItem: add(menuItems, 'nestedmenuitem'),
30665
        addToggleMenuItem: add(menuItems, 'togglemenuitem'),
30666
        addAutocompleter: add(popups, 'autocompleter'),
30667
        addContextMenu: add(contextMenus, 'contextmenu'),
30668
        addContextToolbar: add(contextToolbars, 'contexttoolbar'),
30669
        addContextForm: add(contextToolbars, 'contextform'),
30670
        addSidebar: add(sidebars, 'sidebar'),
30671
        addView: add(views, 'views'),
30672
        addIcon,
30673
        getAll: () => ({
30674
          buttons,
30675
          menuItems,
30676
          icons,
30677
          popups,
30678
          contextMenus,
30679
          contextToolbars,
30680
          sidebars,
30681
          views
30682
        })
30683
      };
30684
    };
30685
 
30686
    const registry = () => {
30687
      const bridge = create$3();
30688
      return {
30689
        addAutocompleter: bridge.addAutocompleter,
30690
        addButton: bridge.addButton,
30691
        addContextForm: bridge.addContextForm,
30692
        addContextMenu: bridge.addContextMenu,
30693
        addContextToolbar: bridge.addContextToolbar,
30694
        addIcon: bridge.addIcon,
30695
        addMenuButton: bridge.addMenuButton,
30696
        addMenuItem: bridge.addMenuItem,
30697
        addNestedMenuItem: bridge.addNestedMenuItem,
30698
        addSidebar: bridge.addSidebar,
30699
        addSplitButton: bridge.addSplitButton,
30700
        addToggleButton: bridge.addToggleButton,
30701
        addGroupToolbarButton: bridge.addGroupToolbarButton,
30702
        addToggleMenuItem: bridge.addToggleMenuItem,
30703
        addView: bridge.addView,
30704
        getAll: bridge.getAll
30705
      };
30706
    };
30707
 
30708
    const DOM$1 = DOMUtils.DOM;
30709
    const extend = Tools.extend, each$1 = Tools.each;
30710
    class Editor {
30711
      constructor(id, options, editorManager) {
30712
        this.plugins = {};
30713
        this.contentCSS = [];
30714
        this.contentStyles = [];
30715
        this.loadedCSS = {};
30716
        this.isNotDirty = false;
30717
        this.composing = false;
30718
        this.destroyed = false;
30719
        this.hasHiddenInput = false;
30720
        this.iframeElement = null;
30721
        this.initialized = false;
30722
        this.readonly = false;
30723
        this.removed = false;
30724
        this.startContent = '';
30725
        this._pendingNativeEvents = [];
30726
        this._skinLoaded = false;
30727
        this._editableRoot = true;
30728
        this.editorManager = editorManager;
30729
        this.documentBaseUrl = editorManager.documentBaseURL;
30730
        extend(this, EditorObservable);
30731
        const self = this;
30732
        this.id = id;
30733
        this.hidden = false;
30734
        const normalizedOptions = normalizeOptions(editorManager.defaultOptions, options);
30735
        this.options = create$5(self, normalizedOptions);
30736
        register$7(self);
30737
        const getOption = this.options.get;
30738
        if (getOption('deprecation_warnings')) {
30739
          logWarnings(options, normalizedOptions);
30740
        }
30741
        const suffix = getOption('suffix');
30742
        if (suffix) {
30743
          editorManager.suffix = suffix;
30744
        }
30745
        this.suffix = editorManager.suffix;
30746
        const baseUrl = getOption('base_url');
30747
        if (baseUrl) {
30748
          editorManager._setBaseUrl(baseUrl);
30749
        }
30750
        this.baseUri = editorManager.baseURI;
30751
        const referrerPolicy = getReferrerPolicy(self);
30752
        if (referrerPolicy) {
30753
          ScriptLoader.ScriptLoader._setReferrerPolicy(referrerPolicy);
30754
          DOMUtils.DOM.styleSheetLoader._setReferrerPolicy(referrerPolicy);
30755
        }
30756
        const contentCssCors = hasContentCssCors(self);
30757
        if (isNonNullable(contentCssCors)) {
30758
          DOMUtils.DOM.styleSheetLoader._setContentCssCors(contentCssCors);
30759
        }
30760
        AddOnManager.languageLoad = getOption('language_load');
30761
        AddOnManager.baseURL = editorManager.baseURL;
30762
        this.setDirty(false);
30763
        this.documentBaseURI = new URI(getDocumentBaseUrl(self), { base_uri: this.baseUri });
30764
        this.baseURI = this.baseUri;
30765
        this.inline = isInline$1(self);
30766
        this.hasVisual = isVisualAidsEnabled(self);
30767
        this.shortcuts = new Shortcuts(this);
30768
        this.editorCommands = new EditorCommands(this);
30769
        registerCommands(this);
30770
        const cacheSuffix = getOption('cache_suffix');
30771
        if (cacheSuffix) {
30772
          Env.cacheSuffix = cacheSuffix.replace(/^[\?\&]+/, '');
30773
        }
30774
        this.ui = {
30775
          registry: registry(),
30776
          styleSheetLoader: undefined,
30777
          show: noop,
30778
          hide: noop,
30779
          setEnabled: noop,
30780
          isEnabled: always
30781
        };
30782
        this.mode = create$4(self);
30783
        editorManager.dispatch('SetupEditor', { editor: this });
30784
        const setupCallback = getSetupCallback(self);
30785
        if (isFunction(setupCallback)) {
30786
          setupCallback.call(self, self);
30787
        }
30788
      }
30789
      render() {
30790
        render(this);
30791
      }
30792
      focus(skipFocus) {
30793
        this.execCommand('mceFocus', false, skipFocus);
30794
      }
30795
      hasFocus() {
30796
        return hasFocus(this);
30797
      }
30798
      translate(text) {
30799
        return I18n.translate(text);
30800
      }
30801
      getParam(name, defaultVal, type) {
30802
        const options = this.options;
30803
        if (!options.isRegistered(name)) {
30804
          if (isNonNullable(type)) {
30805
            options.register(name, {
30806
              processor: type,
30807
              default: defaultVal
30808
            });
30809
          } else {
30810
            options.register(name, {
30811
              processor: always,
30812
              default: defaultVal
30813
            });
30814
          }
30815
        }
30816
        return !options.isSet(name) && !isUndefined(defaultVal) ? defaultVal : options.get(name);
30817
      }
30818
      hasPlugin(name, loaded) {
30819
        const hasPlugin = contains$2(getPlugins(this), name);
30820
        if (hasPlugin) {
30821
          return loaded ? PluginManager.get(name) !== undefined : true;
30822
        } else {
30823
          return false;
30824
        }
30825
      }
30826
      nodeChanged(args) {
30827
        this._nodeChangeDispatcher.nodeChanged(args);
30828
      }
30829
      addCommand(name, callback, scope) {
30830
        this.editorCommands.addCommand(name, callback, scope);
30831
      }
30832
      addQueryStateHandler(name, callback, scope) {
30833
        this.editorCommands.addQueryStateHandler(name, callback, scope);
30834
      }
30835
      addQueryValueHandler(name, callback, scope) {
30836
        this.editorCommands.addQueryValueHandler(name, callback, scope);
30837
      }
30838
      addShortcut(pattern, desc, cmdFunc, scope) {
30839
        this.shortcuts.add(pattern, desc, cmdFunc, scope);
30840
      }
30841
      execCommand(cmd, ui, value, args) {
30842
        return this.editorCommands.execCommand(cmd, ui, value, args);
30843
      }
30844
      queryCommandState(cmd) {
30845
        return this.editorCommands.queryCommandState(cmd);
30846
      }
30847
      queryCommandValue(cmd) {
30848
        return this.editorCommands.queryCommandValue(cmd);
30849
      }
30850
      queryCommandSupported(cmd) {
30851
        return this.editorCommands.queryCommandSupported(cmd);
30852
      }
30853
      show() {
30854
        const self = this;
30855
        if (self.hidden) {
30856
          self.hidden = false;
30857
          if (self.inline) {
30858
            self.getBody().contentEditable = 'true';
30859
          } else {
30860
            DOM$1.show(self.getContainer());
30861
            DOM$1.hide(self.id);
30862
          }
30863
          self.load();
30864
          self.dispatch('show');
30865
        }
30866
      }
30867
      hide() {
30868
        const self = this;
30869
        if (!self.hidden) {
30870
          self.save();
30871
          if (self.inline) {
30872
            self.getBody().contentEditable = 'false';
30873
            if (self === self.editorManager.focusedEditor) {
30874
              self.editorManager.focusedEditor = null;
30875
            }
30876
          } else {
30877
            DOM$1.hide(self.getContainer());
30878
            DOM$1.setStyle(self.id, 'display', self.orgDisplay);
30879
          }
30880
          self.hidden = true;
30881
          self.dispatch('hide');
30882
        }
30883
      }
30884
      isHidden() {
30885
        return this.hidden;
30886
      }
30887
      setProgressState(state, time) {
30888
        this.dispatch('ProgressState', {
30889
          state,
30890
          time
30891
        });
30892
      }
30893
      load(args = {}) {
30894
        const self = this;
30895
        const elm = self.getElement();
30896
        if (self.removed) {
30897
          return '';
30898
        }
30899
        if (elm) {
30900
          const loadArgs = {
30901
            ...args,
30902
            load: true
30903
          };
30904
          const value = isTextareaOrInput(elm) ? elm.value : elm.innerHTML;
30905
          const html = self.setContent(value, loadArgs);
30906
          if (!loadArgs.no_events) {
30907
            self.dispatch('LoadContent', {
30908
              ...loadArgs,
30909
              element: elm
30910
            });
30911
          }
30912
          return html;
30913
        } else {
30914
          return '';
30915
        }
30916
      }
30917
      save(args = {}) {
30918
        const self = this;
30919
        let elm = self.getElement();
30920
        if (!elm || !self.initialized || self.removed) {
30921
          return '';
30922
        }
30923
        const getArgs = {
30924
          ...args,
30925
          save: true,
30926
          element: elm
30927
        };
30928
        let html = self.getContent(getArgs);
30929
        const saveArgs = {
30930
          ...getArgs,
30931
          content: html
30932
        };
30933
        if (!saveArgs.no_events) {
30934
          self.dispatch('SaveContent', saveArgs);
30935
        }
30936
        if (saveArgs.format === 'raw') {
30937
          self.dispatch('RawSaveContent', saveArgs);
30938
        }
30939
        html = saveArgs.content;
30940
        if (!isTextareaOrInput(elm)) {
30941
          if (args.is_removing || !self.inline) {
30942
            elm.innerHTML = html;
30943
          }
30944
          const form = DOM$1.getParent(self.id, 'form');
30945
          if (form) {
30946
            each$1(form.elements, elm => {
30947
              if (elm.name === self.id) {
30948
                elm.value = html;
30949
                return false;
30950
              } else {
30951
                return true;
30952
              }
30953
            });
30954
          }
30955
        } else {
30956
          elm.value = html;
30957
        }
30958
        saveArgs.element = getArgs.element = elm = null;
30959
        if (saveArgs.set_dirty !== false) {
30960
          self.setDirty(false);
30961
        }
30962
        return html;
30963
      }
30964
      setContent(content, args) {
30965
        return setContent(this, content, args);
30966
      }
30967
      getContent(args) {
30968
        return getContent(this, args);
30969
      }
30970
      insertContent(content, args) {
30971
        if (args) {
30972
          content = extend({ content }, args);
30973
        }
30974
        this.execCommand('mceInsertContent', false, content);
30975
      }
30976
      resetContent(initialContent) {
30977
        if (initialContent === undefined) {
30978
          setContent(this, this.startContent, { format: 'raw' });
30979
        } else {
30980
          setContent(this, initialContent);
30981
        }
30982
        this.undoManager.reset();
30983
        this.setDirty(false);
30984
        this.nodeChanged();
30985
      }
30986
      isDirty() {
30987
        return !this.isNotDirty;
30988
      }
30989
      setDirty(state) {
30990
        const oldState = !this.isNotDirty;
30991
        this.isNotDirty = !state;
30992
        if (state && state !== oldState) {
30993
          this.dispatch('dirty');
30994
        }
30995
      }
30996
      getContainer() {
30997
        const self = this;
30998
        if (!self.container) {
30999
          self.container = self.editorContainer || DOM$1.get(self.id + '_parent');
31000
        }
31001
        return self.container;
31002
      }
31003
      getContentAreaContainer() {
31004
        return this.contentAreaContainer;
31005
      }
31006
      getElement() {
31007
        if (!this.targetElm) {
31008
          this.targetElm = DOM$1.get(this.id);
31009
        }
31010
        return this.targetElm;
31011
      }
31012
      getWin() {
31013
        const self = this;
31014
        if (!self.contentWindow) {
31015
          const elm = self.iframeElement;
31016
          if (elm) {
31017
            self.contentWindow = elm.contentWindow;
31018
          }
31019
        }
31020
        return self.contentWindow;
31021
      }
31022
      getDoc() {
31023
        const self = this;
31024
        if (!self.contentDocument) {
31025
          const win = self.getWin();
31026
          if (win) {
31027
            self.contentDocument = win.document;
31028
          }
31029
        }
31030
        return self.contentDocument;
31031
      }
31032
      getBody() {
31033
        var _a, _b;
31034
        const doc = this.getDoc();
31035
        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;
31036
      }
31037
      convertURL(url, name, elm) {
31038
        const self = this, getOption = self.options.get;
31039
        const urlConverterCallback = getUrlConverterCallback(self);
31040
        if (isFunction(urlConverterCallback)) {
31041
          return urlConverterCallback.call(self, url, elm, true, name);
31042
        }
31043
        if (!getOption('convert_urls') || elm === 'link' || isObject(elm) && elm.nodeName === 'LINK' || url.indexOf('file:') === 0 || url.length === 0) {
31044
          return url;
31045
        }
31046
        const urlObject = new URI(url);
31047
        if (urlObject.protocol !== 'http' && urlObject.protocol !== 'https' && urlObject.protocol !== '') {
31048
          return url;
31049
        }
31050
        if (getOption('relative_urls')) {
31051
          return self.documentBaseURI.toRelative(url);
31052
        }
31053
        url = self.documentBaseURI.toAbsolute(url, getOption('remove_script_host'));
31054
        return url;
31055
      }
31056
      addVisual(elm) {
31057
        addVisual(this, elm);
31058
      }
31059
      setEditableRoot(state) {
31060
        setEditableRoot(this, state);
31061
      }
31062
      hasEditableRoot() {
31063
        return hasEditableRoot(this);
31064
      }
31065
      remove() {
31066
        remove$1(this);
31067
      }
31068
      destroy(automatic) {
31069
        destroy(this, automatic);
31070
      }
31071
      uploadImages() {
31072
        return this.editorUpload.uploadImages();
31073
      }
31074
      _scanForImages() {
31075
        return this.editorUpload.scanForImages();
31076
      }
31077
    }
31078
 
31079
    const DOM = DOMUtils.DOM;
31080
    const each = Tools.each;
31081
    let boundGlobalEvents = false;
31082
    let beforeUnloadDelegate;
31083
    let editors = [];
31084
    const globalEventDelegate = e => {
31085
      const type = e.type;
31086
      each(EditorManager.get(), editor => {
31087
        switch (type) {
31088
        case 'scroll':
31089
          editor.dispatch('ScrollWindow', e);
31090
          break;
31091
        case 'resize':
31092
          editor.dispatch('ResizeWindow', e);
31093
          break;
31094
        }
31095
      });
31096
    };
31097
    const toggleGlobalEvents = state => {
31098
      if (state !== boundGlobalEvents) {
31099
        const DOM = DOMUtils.DOM;
31100
        if (state) {
31101
          DOM.bind(window, 'resize', globalEventDelegate);
31102
          DOM.bind(window, 'scroll', globalEventDelegate);
31103
        } else {
31104
          DOM.unbind(window, 'resize', globalEventDelegate);
31105
          DOM.unbind(window, 'scroll', globalEventDelegate);
31106
        }
31107
        boundGlobalEvents = state;
31108
      }
31109
    };
31110
    const removeEditorFromList = targetEditor => {
31111
      const oldEditors = editors;
31112
      editors = filter$5(editors, editor => {
31113
        return targetEditor !== editor;
31114
      });
31115
      if (EditorManager.activeEditor === targetEditor) {
31116
        EditorManager.activeEditor = editors.length > 0 ? editors[0] : null;
31117
      }
31118
      if (EditorManager.focusedEditor === targetEditor) {
31119
        EditorManager.focusedEditor = null;
31120
      }
31121
      return oldEditors.length !== editors.length;
31122
    };
31123
    const purgeDestroyedEditor = editor => {
31124
      if (editor && editor.initialized && !(editor.getContainer() || editor.getBody()).parentNode) {
31125
        removeEditorFromList(editor);
31126
        editor.unbindAllNativeEvents();
31127
        editor.destroy(true);
31128
        editor.removed = true;
31129
      }
31130
    };
31131
    const isQuirksMode = document.compatMode !== 'CSS1Compat';
31132
    const EditorManager = {
31133
      ...Observable,
31134
      baseURI: null,
31135
      baseURL: null,
31136
      defaultOptions: {},
31137
      documentBaseURL: null,
31138
      suffix: null,
31139
      majorVersion: '6',
31140
      minorVersion: '8.3',
31141
      releaseDate: '2024-02-08',
31142
      i18n: I18n,
31143
      activeEditor: null,
31144
      focusedEditor: null,
31145
      setup() {
31146
        const self = this;
31147
        let baseURL = '';
31148
        let suffix = '';
31149
        let documentBaseURL = URI.getDocumentBaseUrl(document.location);
31150
        if (/^[^:]+:\/\/\/?[^\/]+\//.test(documentBaseURL)) {
31151
          documentBaseURL = documentBaseURL.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
31152
          if (!/[\/\\]$/.test(documentBaseURL)) {
31153
            documentBaseURL += '/';
31154
          }
31155
        }
31156
        const preInit = window.tinymce || window.tinyMCEPreInit;
31157
        if (preInit) {
31158
          baseURL = preInit.base || preInit.baseURL;
31159
          suffix = preInit.suffix;
31160
        } else {
31161
          const scripts = document.getElementsByTagName('script');
31162
          for (let i = 0; i < scripts.length; i++) {
31163
            const src = scripts[i].src || '';
31164
            if (src === '') {
31165
              continue;
31166
            }
31167
            const srcScript = src.substring(src.lastIndexOf('/'));
31168
            if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
31169
              if (srcScript.indexOf('.min') !== -1) {
31170
                suffix = '.min';
31171
              }
31172
              baseURL = src.substring(0, src.lastIndexOf('/'));
31173
              break;
31174
            }
31175
          }
31176
          if (!baseURL && document.currentScript) {
31177
            const src = document.currentScript.src;
31178
            if (src.indexOf('.min') !== -1) {
31179
              suffix = '.min';
31180
            }
31181
            baseURL = src.substring(0, src.lastIndexOf('/'));
31182
          }
31183
        }
31184
        self.baseURL = new URI(documentBaseURL).toAbsolute(baseURL);
31185
        self.documentBaseURL = documentBaseURL;
31186
        self.baseURI = new URI(self.baseURL);
31187
        self.suffix = suffix;
31188
        setup$w(self);
31189
      },
31190
      overrideDefaults(defaultOptions) {
31191
        const baseUrl = defaultOptions.base_url;
31192
        if (baseUrl) {
31193
          this._setBaseUrl(baseUrl);
31194
        }
31195
        const suffix = defaultOptions.suffix;
31196
        if (suffix) {
31197
          this.suffix = suffix;
31198
        }
31199
        this.defaultOptions = defaultOptions;
31200
        const pluginBaseUrls = defaultOptions.plugin_base_urls;
31201
        if (pluginBaseUrls !== undefined) {
31202
          each$d(pluginBaseUrls, (pluginBaseUrl, pluginName) => {
31203
            AddOnManager.PluginManager.urls[pluginName] = pluginBaseUrl;
31204
          });
31205
        }
31206
      },
31207
      init(options) {
31208
        const self = this;
31209
        let result;
31210
        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', ' ');
31211
        const isInvalidInlineTarget = (options, elm) => options.inline && elm.tagName.toLowerCase() in invalidInlineTargets;
31212
        const createId = elm => {
31213
          let id = elm.id;
31214
          if (!id) {
31215
            id = get$a(elm, 'name').filter(name => !DOM.get(name)).getOrThunk(DOM.uniqueId);
31216
            elm.setAttribute('id', id);
31217
          }
31218
          return id;
31219
        };
31220
        const execCallback = name => {
31221
          const callback = options[name];
31222
          if (!callback) {
31223
            return;
31224
          }
31225
          return callback.apply(self, []);
31226
        };
31227
        const findTargets = options => {
31228
          if (Env.browser.isIE() || Env.browser.isEdge()) {
31229
            initError('TinyMCE does not support the browser you are using. For a list of supported' + ' browsers please see: https://www.tiny.cloud/docs/tinymce/6/support/#supportedwebbrowsers');
31230
            return [];
31231
          } else if (isQuirksMode) {
31232
            initError('Failed to initialize the editor as the document is not in standards mode. ' + 'TinyMCE requires standards mode.');
31233
            return [];
31234
          } else if (isString(options.selector)) {
31235
            return DOM.select(options.selector);
31236
          } else if (isNonNullable(options.target)) {
31237
            return [options.target];
31238
          } else {
31239
            return [];
31240
          }
31241
        };
31242
        let provideResults = editors => {
31243
          result = editors;
31244
        };
31245
        const initEditors = () => {
31246
          let initCount = 0;
31247
          const editors = [];
31248
          let targets;
31249
          const createEditor = (id, options, targetElm) => {
31250
            const editor = new Editor(id, options, self);
31251
            editors.push(editor);
31252
            editor.on('init', () => {
31253
              if (++initCount === targets.length) {
31254
                provideResults(editors);
31255
              }
31256
            });
31257
            editor.targetElm = editor.targetElm || targetElm;
31258
            editor.render();
31259
          };
31260
          DOM.unbind(window, 'ready', initEditors);
31261
          execCallback('onpageload');
31262
          targets = unique$1(findTargets(options));
31263
          Tools.each(targets, elm => {
31264
            purgeDestroyedEditor(self.get(elm.id));
31265
          });
31266
          targets = Tools.grep(targets, elm => {
31267
            return !self.get(elm.id);
31268
          });
31269
          if (targets.length === 0) {
31270
            provideResults([]);
31271
          } else {
31272
            each(targets, elm => {
31273
              if (isInvalidInlineTarget(options, elm)) {
31274
                initError('Could not initialize inline editor on invalid inline target element', elm);
31275
              } else {
31276
                createEditor(createId(elm), options, elm);
31277
              }
31278
            });
31279
          }
31280
        };
31281
        DOM.bind(window, 'ready', initEditors);
31282
        return new Promise(resolve => {
31283
          if (result) {
31284
            resolve(result);
31285
          } else {
31286
            provideResults = editors => {
31287
              resolve(editors);
31288
            };
31289
          }
31290
        });
31291
      },
31292
      get(id) {
31293
        if (arguments.length === 0) {
31294
          return editors.slice(0);
31295
        } else if (isString(id)) {
31296
          return find$2(editors, editor => {
31297
            return editor.id === id;
31298
          }).getOr(null);
31299
        } else if (isNumber(id)) {
31300
          return editors[id] ? editors[id] : null;
31301
        } else {
31302
          return null;
31303
        }
31304
      },
31305
      add(editor) {
31306
        const self = this;
31307
        const existingEditor = self.get(editor.id);
31308
        if (existingEditor === editor) {
31309
          return editor;
31310
        }
31311
        if (existingEditor === null) {
31312
          editors.push(editor);
31313
        }
31314
        toggleGlobalEvents(true);
31315
        self.activeEditor = editor;
31316
        self.dispatch('AddEditor', { editor });
31317
        if (!beforeUnloadDelegate) {
31318
          beforeUnloadDelegate = e => {
31319
            const event = self.dispatch('BeforeUnload');
31320
            if (event.returnValue) {
31321
              e.preventDefault();
31322
              e.returnValue = event.returnValue;
31323
              return event.returnValue;
31324
            }
31325
          };
31326
          window.addEventListener('beforeunload', beforeUnloadDelegate);
31327
        }
31328
        return editor;
31329
      },
31330
      createEditor(id, options) {
31331
        return this.add(new Editor(id, options, this));
31332
      },
31333
      remove(selector) {
31334
        const self = this;
31335
        let editor;
31336
        if (!selector) {
31337
          for (let i = editors.length - 1; i >= 0; i--) {
31338
            self.remove(editors[i]);
31339
          }
31340
          return;
31341
        }
31342
        if (isString(selector)) {
31343
          each(DOM.select(selector), elm => {
31344
            editor = self.get(elm.id);
31345
            if (editor) {
31346
              self.remove(editor);
31347
            }
31348
          });
31349
          return;
31350
        }
31351
        editor = selector;
31352
        if (isNull(self.get(editor.id))) {
31353
          return null;
31354
        }
31355
        if (removeEditorFromList(editor)) {
31356
          self.dispatch('RemoveEditor', { editor });
31357
        }
31358
        if (editors.length === 0) {
31359
          window.removeEventListener('beforeunload', beforeUnloadDelegate);
31360
        }
31361
        editor.remove();
31362
        toggleGlobalEvents(editors.length > 0);
31363
        return editor;
31364
      },
31365
      execCommand(cmd, ui, value) {
31366
        var _a;
31367
        const self = this;
31368
        const editorId = isObject(value) ? (_a = value.id) !== null && _a !== void 0 ? _a : value.index : value;
31369
        switch (cmd) {
31370
        case 'mceAddEditor': {
31371
            if (!self.get(editorId)) {
31372
              const editorOptions = value.options;
31373
              new Editor(editorId, editorOptions, self).render();
31374
            }
31375
            return true;
31376
          }
31377
        case 'mceRemoveEditor': {
31378
            const editor = self.get(editorId);
31379
            if (editor) {
31380
              editor.remove();
31381
            }
31382
            return true;
31383
          }
31384
        case 'mceToggleEditor': {
31385
            const editor = self.get(editorId);
31386
            if (!editor) {
31387
              self.execCommand('mceAddEditor', false, value);
31388
              return true;
31389
            }
31390
            if (editor.isHidden()) {
31391
              editor.show();
31392
            } else {
31393
              editor.hide();
31394
            }
31395
            return true;
31396
          }
31397
        }
31398
        if (self.activeEditor) {
31399
          return self.activeEditor.execCommand(cmd, ui, value);
31400
        }
31401
        return false;
31402
      },
31403
      triggerSave: () => {
31404
        each(editors, editor => {
31405
          editor.save();
31406
        });
31407
      },
31408
      addI18n: (code, items) => {
31409
        I18n.add(code, items);
31410
      },
31411
      translate: text => {
31412
        return I18n.translate(text);
31413
      },
31414
      setActive(editor) {
31415
        const activeEditor = this.activeEditor;
31416
        if (this.activeEditor !== editor) {
31417
          if (activeEditor) {
31418
            activeEditor.dispatch('deactivate', { relatedTarget: editor });
31419
          }
31420
          editor.dispatch('activate', { relatedTarget: activeEditor });
31421
        }
31422
        this.activeEditor = editor;
31423
      },
31424
      _setBaseUrl(baseUrl) {
31425
        this.baseURL = new URI(this.documentBaseURL).toAbsolute(baseUrl.replace(/\/+$/, ''));
31426
        this.baseURI = new URI(this.baseURL);
31427
      }
31428
    };
31429
    EditorManager.setup();
31430
 
31431
    const setup = () => {
31432
      const dataValue = value$2();
31433
      const FakeClipboardItem = items => ({
31434
        items,
31435
        types: keys(items),
31436
        getType: type => get$a(items, type).getOrUndefined()
31437
      });
31438
      const write = data => {
31439
        dataValue.set(data);
31440
      };
31441
      const read = () => dataValue.get().getOrUndefined();
31442
      const clear = dataValue.clear;
31443
      return {
31444
        FakeClipboardItem,
31445
        write,
31446
        read,
31447
        clear
31448
      };
31449
    };
31450
    const FakeClipboard = setup();
31451
 
31452
    const min = Math.min, max = Math.max, round = Math.round;
31453
    const relativePosition = (rect, targetRect, rel) => {
31454
      let x = targetRect.x;
31455
      let y = targetRect.y;
31456
      const w = rect.w;
31457
      const h = rect.h;
31458
      const targetW = targetRect.w;
31459
      const targetH = targetRect.h;
31460
      const relChars = (rel || '').split('');
31461
      if (relChars[0] === 'b') {
31462
        y += targetH;
31463
      }
31464
      if (relChars[1] === 'r') {
31465
        x += targetW;
31466
      }
31467
      if (relChars[0] === 'c') {
31468
        y += round(targetH / 2);
31469
      }
31470
      if (relChars[1] === 'c') {
31471
        x += round(targetW / 2);
31472
      }
31473
      if (relChars[3] === 'b') {
31474
        y -= h;
31475
      }
31476
      if (relChars[4] === 'r') {
31477
        x -= w;
31478
      }
31479
      if (relChars[3] === 'c') {
31480
        y -= round(h / 2);
31481
      }
31482
      if (relChars[4] === 'c') {
31483
        x -= round(w / 2);
31484
      }
31485
      return create$2(x, y, w, h);
31486
    };
31487
    const findBestRelativePosition = (rect, targetRect, constrainRect, rels) => {
31488
      for (let i = 0; i < rels.length; i++) {
31489
        const pos = relativePosition(rect, targetRect, rels[i]);
31490
        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) {
31491
          return rels[i];
31492
        }
31493
      }
31494
      return null;
31495
    };
31496
    const inflate = (rect, w, h) => {
31497
      return create$2(rect.x - w, rect.y - h, rect.w + w * 2, rect.h + h * 2);
31498
    };
31499
    const intersect = (rect, cropRect) => {
31500
      const x1 = max(rect.x, cropRect.x);
31501
      const y1 = max(rect.y, cropRect.y);
31502
      const x2 = min(rect.x + rect.w, cropRect.x + cropRect.w);
31503
      const y2 = min(rect.y + rect.h, cropRect.y + cropRect.h);
31504
      if (x2 - x1 < 0 || y2 - y1 < 0) {
31505
        return null;
31506
      }
31507
      return create$2(x1, y1, x2 - x1, y2 - y1);
31508
    };
31509
    const clamp = (rect, clampRect, fixedSize) => {
31510
      let x1 = rect.x;
31511
      let y1 = rect.y;
31512
      let x2 = rect.x + rect.w;
31513
      let y2 = rect.y + rect.h;
31514
      const cx2 = clampRect.x + clampRect.w;
31515
      const cy2 = clampRect.y + clampRect.h;
31516
      const underflowX1 = max(0, clampRect.x - x1);
31517
      const underflowY1 = max(0, clampRect.y - y1);
31518
      const overflowX2 = max(0, x2 - cx2);
31519
      const overflowY2 = max(0, y2 - cy2);
31520
      x1 += underflowX1;
31521
      y1 += underflowY1;
31522
      if (fixedSize) {
31523
        x2 += underflowX1;
31524
        y2 += underflowY1;
31525
        x1 -= overflowX2;
31526
        y1 -= overflowY2;
31527
      }
31528
      x2 -= overflowX2;
31529
      y2 -= overflowY2;
31530
      return create$2(x1, y1, x2 - x1, y2 - y1);
31531
    };
31532
    const create$2 = (x, y, w, h) => {
31533
      return {
31534
        x,
31535
        y,
31536
        w,
31537
        h
31538
      };
31539
    };
31540
    const fromClientRect = clientRect => {
31541
      return create$2(clientRect.left, clientRect.top, clientRect.width, clientRect.height);
31542
    };
31543
    const Rect = {
31544
      inflate,
31545
      relativePosition,
31546
      findBestRelativePosition,
31547
      intersect,
31548
      clamp,
31549
      create: create$2,
31550
      fromClientRect
31551
    };
31552
 
31553
    const awaiter = (resolveCb, rejectCb, timeout = 1000) => {
31554
      let done = false;
31555
      let timer = null;
31556
      const complete = completer => (...args) => {
31557
        if (!done) {
31558
          done = true;
31559
          if (timer !== null) {
31560
            clearTimeout(timer);
31561
            timer = null;
31562
          }
31563
          completer.apply(null, args);
31564
        }
31565
      };
31566
      const resolve = complete(resolveCb);
31567
      const reject = complete(rejectCb);
31568
      const start = (...args) => {
31569
        if (!done && timer === null) {
31570
          timer = setTimeout(() => reject.apply(null, args), timeout);
31571
        }
31572
      };
31573
      return {
31574
        start,
31575
        resolve,
31576
        reject
31577
      };
31578
    };
31579
    const create$1 = () => {
31580
      const tasks = {};
31581
      const resultFns = {};
31582
      const resources = {};
31583
      const load = (id, url) => {
31584
        const loadErrMsg = `Script at URL "${ url }" failed to load`;
31585
        const runErrMsg = `Script at URL "${ url }" did not call \`tinymce.Resource.add('${ id }', data)\` within 1 second`;
31586
        if (tasks[id] !== undefined) {
31587
          return tasks[id];
31588
        } else {
31589
          const task = new Promise((resolve, reject) => {
31590
            const waiter = awaiter(resolve, reject);
31591
            resultFns[id] = waiter.resolve;
31592
            ScriptLoader.ScriptLoader.loadScript(url).then(() => waiter.start(runErrMsg), () => waiter.reject(loadErrMsg));
31593
          });
31594
          tasks[id] = task;
31595
          return task;
31596
        }
31597
      };
31598
      const add = (id, data) => {
31599
        if (resultFns[id] !== undefined) {
31600
          resultFns[id](data);
31601
          delete resultFns[id];
31602
        }
31603
        tasks[id] = Promise.resolve(data);
31604
        resources[id] = data;
31605
      };
31606
      const has = id => {
31607
        return id in resources;
31608
      };
31609
      const unload = id => {
31610
        delete tasks[id];
31611
      };
31612
      const get = id => resources[id];
31613
      return {
31614
        load,
31615
        add,
31616
        has,
31617
        get,
31618
        unload
31619
      };
31620
    };
31621
    const Resource = create$1();
31622
 
31623
    const create = () => (() => {
31624
      let data = {};
31625
      let keys = [];
31626
      const storage = {
31627
        getItem: key => {
31628
          const item = data[key];
31629
          return item ? item : null;
31630
        },
31631
        setItem: (key, value) => {
31632
          keys.push(key);
31633
          data[key] = String(value);
31634
        },
31635
        key: index => {
31636
          return keys[index];
31637
        },
31638
        removeItem: key => {
31639
          keys = keys.filter(k => k === key);
31640
          delete data[key];
31641
        },
31642
        clear: () => {
31643
          keys = [];
31644
          data = {};
31645
        },
31646
        length: 0
31647
      };
31648
      Object.defineProperty(storage, 'length', {
31649
        get: () => keys.length,
31650
        configurable: false,
31651
        enumerable: false
31652
      });
31653
      return storage;
31654
    })();
31655
 
31656
    let localStorage;
31657
    try {
31658
      const test = '__storage_test__';
31659
      localStorage = window.localStorage;
31660
      localStorage.setItem(test, test);
31661
      localStorage.removeItem(test);
31662
    } catch (e) {
31663
      localStorage = create();
31664
    }
31665
    var LocalStorage = localStorage;
31666
 
31667
    const publicApi = {
31668
      geom: { Rect },
31669
      util: {
31670
        Delay,
31671
        Tools,
31672
        VK,
31673
        URI,
31674
        EventDispatcher,
31675
        Observable,
31676
        I18n,
31677
        LocalStorage,
31678
        ImageUploader
31679
      },
31680
      dom: {
31681
        EventUtils,
31682
        TreeWalker: DomTreeWalker,
31683
        TextSeeker,
31684
        DOMUtils,
31685
        ScriptLoader,
31686
        RangeUtils,
31687
        Serializer: DomSerializer,
31688
        StyleSheetLoader,
31689
        ControlSelection,
31690
        BookmarkManager,
31691
        Selection: EditorSelection,
31692
        Event: EventUtils.Event
31693
      },
31694
      html: {
31695
        Styles,
31696
        Entities,
31697
        Node: AstNode,
31698
        Schema,
31699
        DomParser,
31700
        Writer,
31701
        Serializer: HtmlSerializer
31702
      },
31703
      Env,
31704
      AddOnManager,
31705
      Annotator,
31706
      Formatter,
31707
      UndoManager,
31708
      EditorCommands,
31709
      WindowManager,
31710
      NotificationManager,
31711
      EditorObservable,
31712
      Shortcuts,
31713
      Editor,
31714
      FocusManager,
31715
      EditorManager,
31716
      DOM: DOMUtils.DOM,
31717
      ScriptLoader: ScriptLoader.ScriptLoader,
31718
      PluginManager,
31719
      ThemeManager,
31720
      ModelManager,
31721
      IconManager,
31722
      Resource,
31723
      FakeClipboard,
31724
      trim: Tools.trim,
31725
      isArray: Tools.isArray,
31726
      is: Tools.is,
31727
      toArray: Tools.toArray,
31728
      makeMap: Tools.makeMap,
31729
      each: Tools.each,
31730
      map: Tools.map,
31731
      grep: Tools.grep,
31732
      inArray: Tools.inArray,
31733
      extend: Tools.extend,
31734
      walk: Tools.walk,
31735
      resolve: Tools.resolve,
31736
      explode: Tools.explode,
31737
      _addCacheSuffix: Tools._addCacheSuffix
31738
    };
31739
    const tinymce$1 = Tools.extend(EditorManager, publicApi);
31740
 
31741
    const exportToModuleLoaders = tinymce => {
31742
      if (typeof module === 'object') {
31743
        try {
31744
          module.exports = tinymce;
31745
        } catch (_) {
31746
        }
31747
      }
31748
    };
31749
    const exportToWindowGlobal = tinymce => {
31750
      window.tinymce = tinymce;
31751
      window.tinyMCE = tinymce;
31752
    };
31753
    exportToWindowGlobal(tinymce$1);
31754
    exportToModuleLoaders(tinymce$1);
31755
 
31756
})();