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 global$4 = tinymce.util.Tools.resolve('tinymce.PluginManager');
9
 
10
    let unique = 0;
11
    const generate = prefix => {
12
      const date = new Date();
13
      const time = date.getTime();
14
      const random = Math.floor(Math.random() * 1000000000);
15
      unique++;
16
      return prefix + '_' + random + unique + String(time);
17
    };
18
 
19
    const hasProto = (v, constructor, predicate) => {
20
      var _a;
21
      if (predicate(v, constructor.prototype)) {
22
        return true;
23
      } else {
24
        return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
25
      }
26
    };
27
    const typeOf = x => {
28
      const t = typeof x;
29
      if (x === null) {
30
        return 'null';
31
      } else if (t === 'object' && Array.isArray(x)) {
32
        return 'array';
33
      } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
34
        return 'string';
35
      } else {
36
        return t;
37
      }
38
    };
39
    const isType$1 = type => value => typeOf(value) === type;
40
    const isSimpleType = type => value => typeof value === type;
41
    const isString = isType$1('string');
42
    const isBoolean = isSimpleType('boolean');
43
    const isNullable = a => a === null || a === undefined;
44
    const isNonNullable = a => !isNullable(a);
45
    const isFunction = isSimpleType('function');
46
    const isNumber = isSimpleType('number');
47
 
48
    const compose1 = (fbc, fab) => a => fbc(fab(a));
49
    const constant = value => {
50
      return () => {
51
        return value;
52
      };
53
    };
54
    const tripleEquals = (a, b) => {
55
      return a === b;
56
    };
57
    const never = constant(false);
58
 
59
    class Optional {
60
      constructor(tag, value) {
61
        this.tag = tag;
62
        this.value = value;
63
      }
64
      static some(value) {
65
        return new Optional(true, value);
66
      }
67
      static none() {
68
        return Optional.singletonNone;
69
      }
70
      fold(onNone, onSome) {
71
        if (this.tag) {
72
          return onSome(this.value);
73
        } else {
74
          return onNone();
75
        }
76
      }
77
      isSome() {
78
        return this.tag;
79
      }
80
      isNone() {
81
        return !this.tag;
82
      }
83
      map(mapper) {
84
        if (this.tag) {
85
          return Optional.some(mapper(this.value));
86
        } else {
87
          return Optional.none();
88
        }
89
      }
90
      bind(binder) {
91
        if (this.tag) {
92
          return binder(this.value);
93
        } else {
94
          return Optional.none();
95
        }
96
      }
97
      exists(predicate) {
98
        return this.tag && predicate(this.value);
99
      }
100
      forall(predicate) {
101
        return !this.tag || predicate(this.value);
102
      }
103
      filter(predicate) {
104
        if (!this.tag || predicate(this.value)) {
105
          return this;
106
        } else {
107
          return Optional.none();
108
        }
109
      }
110
      getOr(replacement) {
111
        return this.tag ? this.value : replacement;
112
      }
113
      or(replacement) {
114
        return this.tag ? this : replacement;
115
      }
116
      getOrThunk(thunk) {
117
        return this.tag ? this.value : thunk();
118
      }
119
      orThunk(thunk) {
120
        return this.tag ? this : thunk();
121
      }
122
      getOrDie(message) {
123
        if (!this.tag) {
124
          throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
125
        } else {
126
          return this.value;
127
        }
128
      }
129
      static from(value) {
130
        return isNonNullable(value) ? Optional.some(value) : Optional.none();
131
      }
132
      getOrNull() {
133
        return this.tag ? this.value : null;
134
      }
135
      getOrUndefined() {
136
        return this.value;
137
      }
138
      each(worker) {
139
        if (this.tag) {
140
          worker(this.value);
141
        }
142
      }
143
      toArray() {
144
        return this.tag ? [this.value] : [];
145
      }
146
      toString() {
147
        return this.tag ? `some(${ this.value })` : 'none()';
148
      }
149
    }
150
    Optional.singletonNone = new Optional(false);
151
 
152
    const nativeIndexOf = Array.prototype.indexOf;
153
    const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
154
    const contains = (xs, x) => rawIndexOf(xs, x) > -1;
155
    const map = (xs, f) => {
156
      const len = xs.length;
157
      const r = new Array(len);
158
      for (let i = 0; i < len; i++) {
159
        const x = xs[i];
160
        r[i] = f(x, i);
161
      }
162
      return r;
163
    };
164
    const each$1 = (xs, f) => {
165
      for (let i = 0, len = xs.length; i < len; i++) {
166
        const x = xs[i];
167
        f(x, i);
168
      }
169
    };
170
    const filter = (xs, pred) => {
171
      const r = [];
172
      for (let i = 0, len = xs.length; i < len; i++) {
173
        const x = xs[i];
174
        if (pred(x, i)) {
175
          r.push(x);
176
        }
177
      }
178
      return r;
179
    };
180
    const foldl = (xs, f, acc) => {
181
      each$1(xs, (x, i) => {
182
        acc = f(acc, x, i);
183
      });
184
      return acc;
185
    };
186
 
187
    const keys = Object.keys;
188
    const each = (obj, f) => {
189
      const props = keys(obj);
190
      for (let k = 0, len = props.length; k < len; k++) {
191
        const i = props[k];
192
        const x = obj[i];
193
        f(x, i);
194
      }
195
    };
196
 
197
    typeof window !== 'undefined' ? window : Function('return this;')();
198
 
199
    const COMMENT = 8;
200
    const DOCUMENT = 9;
201
    const DOCUMENT_FRAGMENT = 11;
202
    const ELEMENT = 1;
203
    const TEXT = 3;
204
 
205
    const name = element => {
206
      const r = element.dom.nodeName;
207
      return r.toLowerCase();
208
    };
209
    const type = element => element.dom.nodeType;
210
    const isType = t => element => type(element) === t;
211
    const isComment = element => type(element) === COMMENT || name(element) === '#comment';
212
    const isElement = isType(ELEMENT);
213
    const isText = isType(TEXT);
214
    const isDocument = isType(DOCUMENT);
215
    const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
216
 
217
    const rawSet = (dom, key, value) => {
218
      if (isString(value) || isBoolean(value) || isNumber(value)) {
219
        dom.setAttribute(key, value + '');
220
      } else {
221
        console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
222
        throw new Error('Attribute value was not simple');
223
      }
224
    };
225
    const set$2 = (element, key, value) => {
226
      rawSet(element.dom, key, value);
227
    };
228
    const setAll = (element, attrs) => {
229
      const dom = element.dom;
230
      each(attrs, (v, k) => {
231
        rawSet(dom, k, v);
232
      });
233
    };
234
    const get$2 = (element, key) => {
235
      const v = element.dom.getAttribute(key);
236
      return v === null ? undefined : v;
237
    };
238
    const getOpt = (element, key) => Optional.from(get$2(element, key));
239
    const remove$2 = (element, key) => {
240
      element.dom.removeAttribute(key);
241
    };
242
    const clone = element => foldl(element.dom.attributes, (acc, attr) => {
243
      acc[attr.name] = attr.value;
244
      return acc;
245
    }, {});
246
 
247
    const fromHtml = (html, scope) => {
248
      const doc = scope || document;
249
      const div = doc.createElement('div');
250
      div.innerHTML = html;
251
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
252
        const message = 'HTML does not have a single root node';
253
        console.error(message, html);
254
        throw new Error(message);
255
      }
256
      return fromDom(div.childNodes[0]);
257
    };
258
    const fromTag = (tag, scope) => {
259
      const doc = scope || document;
260
      const node = doc.createElement(tag);
261
      return fromDom(node);
262
    };
263
    const fromText = (text, scope) => {
264
      const doc = scope || document;
265
      const node = doc.createTextNode(text);
266
      return fromDom(node);
267
    };
268
    const fromDom = node => {
269
      if (node === null || node === undefined) {
270
        throw new Error('Node cannot be null or undefined');
271
      }
272
      return { dom: node };
273
    };
274
    const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom);
275
    const SugarElement = {
276
      fromHtml,
277
      fromTag,
278
      fromText,
279
      fromDom,
280
      fromPoint
281
    };
282
 
283
    const is$2 = (element, selector) => {
284
      const dom = element.dom;
285
      if (dom.nodeType !== ELEMENT) {
286
        return false;
287
      } else {
288
        const elem = dom;
289
        if (elem.matches !== undefined) {
290
          return elem.matches(selector);
291
        } else if (elem.msMatchesSelector !== undefined) {
292
          return elem.msMatchesSelector(selector);
293
        } else if (elem.webkitMatchesSelector !== undefined) {
294
          return elem.webkitMatchesSelector(selector);
295
        } else if (elem.mozMatchesSelector !== undefined) {
296
          return elem.mozMatchesSelector(selector);
297
        } else {
298
          throw new Error('Browser lacks native selectors');
299
        }
300
      }
301
    };
302
    const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
303
    const all = (selector, scope) => {
304
      const base = scope === undefined ? document : scope.dom;
305
      return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), SugarElement.fromDom);
306
    };
307
    const one = (selector, scope) => {
308
      const base = scope === undefined ? document : scope.dom;
309
      return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
310
    };
311
 
312
    const eq = (e1, e2) => e1.dom === e2.dom;
313
    const is$1 = is$2;
314
 
315
    const is = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
316
 
317
    const blank = r => s => s.replace(r, '');
318
    const trim = blank(/^\s+|\s+$/g);
319
 
320
    const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
321
 
322
    const owner = element => SugarElement.fromDom(element.dom.ownerDocument);
323
    const documentOrOwner = dos => isDocument(dos) ? dos : owner(dos);
324
    const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
325
    const parents = (element, isRoot) => {
326
      const stop = isFunction(isRoot) ? isRoot : never;
327
      let dom = element.dom;
328
      const ret = [];
329
      while (dom.parentNode !== null && dom.parentNode !== undefined) {
330
        const rawParent = dom.parentNode;
331
        const p = SugarElement.fromDom(rawParent);
332
        ret.push(p);
333
        if (stop(p) === true) {
334
          break;
335
        } else {
336
          dom = rawParent;
337
        }
338
      }
339
      return ret;
340
    };
341
    const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
342
    const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
343
    const children = element => map(element.dom.childNodes, SugarElement.fromDom);
344
    const child = (element, index) => {
345
      const cs = element.dom.childNodes;
346
      return Optional.from(cs[index]).map(SugarElement.fromDom);
347
    };
348
    const firstChild = element => child(element, 0);
349
 
350
    const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
351
    const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
352
    const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
353
    const getShadowRoot = e => {
354
      const r = getRootNode(e);
355
      return isShadowRoot(r) ? Optional.some(r) : Optional.none();
356
    };
357
    const getShadowHost = e => SugarElement.fromDom(e.dom.host);
358
 
359
    const inBody = element => {
360
      const dom = isText(element) ? element.dom.parentNode : element.dom;
361
      if (dom === undefined || dom === null || dom.ownerDocument === null) {
362
        return false;
363
      }
364
      const doc = dom.ownerDocument;
365
      return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
366
    };
367
 
368
    const internalSet = (dom, property, value) => {
369
      if (!isString(value)) {
370
        console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
371
        throw new Error('CSS value must be a string: ' + value);
372
      }
373
      if (isSupported(dom)) {
374
        dom.style.setProperty(property, value);
375
      }
376
    };
377
    const internalRemove = (dom, property) => {
378
      if (isSupported(dom)) {
379
        dom.style.removeProperty(property);
380
      }
381
    };
382
    const set$1 = (element, property, value) => {
383
      const dom = element.dom;
384
      internalSet(dom, property, value);
385
    };
386
    const get$1 = (element, property) => {
387
      const dom = element.dom;
388
      const styles = window.getComputedStyle(dom);
389
      const r = styles.getPropertyValue(property);
390
      return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
391
    };
392
    const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : '';
393
    const getRaw = (element, property) => {
394
      const dom = element.dom;
395
      const raw = getUnsafeProperty(dom, property);
396
      return Optional.from(raw).filter(r => r.length > 0);
397
    };
398
    const remove$1 = (element, property) => {
399
      const dom = element.dom;
400
      internalRemove(dom, property);
401
      if (is(getOpt(element, 'style').map(trim), '')) {
402
        remove$2(element, 'style');
403
      }
404
    };
405
 
406
    const before = (marker, element) => {
407
      const parent$1 = parent(marker);
408
      parent$1.each(v => {
409
        v.dom.insertBefore(element.dom, marker.dom);
410
      });
411
    };
412
    const after$1 = (marker, element) => {
413
      const sibling = nextSibling(marker);
414
      sibling.fold(() => {
415
        const parent$1 = parent(marker);
416
        parent$1.each(v => {
417
          append$1(v, element);
418
        });
419
      }, v => {
420
        before(v, element);
421
      });
422
    };
423
    const prepend = (parent, element) => {
424
      const firstChild$1 = firstChild(parent);
425
      firstChild$1.fold(() => {
426
        append$1(parent, element);
427
      }, v => {
428
        parent.dom.insertBefore(element.dom, v.dom);
429
      });
430
    };
431
    const append$1 = (parent, element) => {
432
      parent.dom.appendChild(element.dom);
433
    };
434
    const wrap = (element, wrapper) => {
435
      before(element, wrapper);
436
      append$1(wrapper, element);
437
    };
438
 
439
    const after = (marker, elements) => {
440
      each$1(elements, (x, i) => {
441
        const e = i === 0 ? marker : elements[i - 1];
442
        after$1(e, x);
443
      });
444
    };
445
    const append = (parent, elements) => {
446
      each$1(elements, x => {
447
        append$1(parent, x);
448
      });
449
    };
450
 
451
    const descendants$1 = (scope, predicate) => {
452
      let result = [];
453
      each$1(children(scope), x => {
454
        if (predicate(x)) {
455
          result = result.concat([x]);
456
        }
457
        result = result.concat(descendants$1(x, predicate));
458
      });
459
      return result;
460
    };
461
 
462
    var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
463
      if (is(scope, a)) {
464
        return Optional.some(scope);
465
      } else if (isFunction(isRoot) && isRoot(scope)) {
466
        return Optional.none();
467
      } else {
468
        return ancestor(scope, a, isRoot);
469
      }
470
    };
471
 
472
    const ancestor$1 = (scope, predicate, isRoot) => {
473
      let element = scope.dom;
474
      const stop = isFunction(isRoot) ? isRoot : never;
475
      while (element.parentNode) {
476
        element = element.parentNode;
477
        const el = SugarElement.fromDom(element);
478
        if (predicate(el)) {
479
          return Optional.some(el);
480
        } else if (stop(el)) {
481
          break;
482
        }
483
      }
484
      return Optional.none();
485
    };
486
 
487
    const remove = element => {
488
      const dom = element.dom;
489
      if (dom.parentNode !== null) {
490
        dom.parentNode.removeChild(dom);
491
      }
492
    };
493
    const unwrap = wrapper => {
494
      const children$1 = children(wrapper);
495
      if (children$1.length > 0) {
496
        after(wrapper, children$1);
497
      }
498
      remove(wrapper);
499
    };
500
 
501
    const descendants = (scope, selector) => all(selector, scope);
502
 
503
    const ancestor = (scope, selector, isRoot) => ancestor$1(scope, e => is$2(e, selector), isRoot);
504
    const descendant = (scope, selector) => one(selector, scope);
505
    const closest = (scope, selector, isRoot) => {
506
      const is = (element, selector) => is$2(element, selector);
507
      return ClosestOrAncestor(is, ancestor, scope, selector, isRoot);
508
    };
509
 
510
    const NodeValue = (is, name) => {
511
      const get = element => {
512
        if (!is(element)) {
513
          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
514
        }
515
        return getOption(element).getOr('');
516
      };
517
      const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
518
      const set = (element, value) => {
519
        if (!is(element)) {
520
          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
521
        }
522
        element.dom.nodeValue = value;
523
      };
524
      return {
525
        get,
526
        getOption,
527
        set
528
      };
529
    };
530
 
531
    const api = NodeValue(isText, 'text');
532
    const get = element => api.get(element);
533
    const set = (element, value) => api.set(element, value);
534
 
535
    var TagBoundaries = [
536
      'body',
537
      'p',
538
      'div',
539
      'article',
540
      'aside',
541
      'figcaption',
542
      'figure',
543
      'footer',
544
      'header',
545
      'nav',
546
      'section',
547
      'ol',
548
      'ul',
549
      'li',
550
      'table',
551
      'thead',
552
      'tbody',
553
      'tfoot',
554
      'caption',
555
      'tr',
556
      'td',
557
      'th',
558
      'h1',
559
      'h2',
560
      'h3',
561
      'h4',
562
      'h5',
563
      'h6',
564
      'blockquote',
565
      'pre',
566
      'address'
567
    ];
568
 
569
    var DomUniverse = () => {
570
      const clone$1 = element => {
571
        return SugarElement.fromDom(element.dom.cloneNode(false));
572
      };
573
      const document = element => documentOrOwner(element).dom;
574
      const isBoundary = element => {
575
        if (!isElement(element)) {
576
          return false;
577
        }
578
        if (name(element) === 'body') {
579
          return true;
580
        }
581
        return contains(TagBoundaries, name(element));
582
      };
583
      const isEmptyTag = element => {
584
        if (!isElement(element)) {
585
          return false;
586
        }
587
        return contains([
588
          'br',
589
          'img',
590
          'hr',
591
          'input'
592
        ], name(element));
593
      };
594
      const isNonEditable = element => isElement(element) && get$2(element, 'contenteditable') === 'false';
595
      const comparePosition = (element, other) => {
596
        return element.dom.compareDocumentPosition(other.dom);
597
      };
598
      const copyAttributesTo = (source, destination) => {
599
        const as = clone(source);
600
        setAll(destination, as);
601
      };
602
      const isSpecial = element => {
603
        const tag = name(element);
604
        return contains([
605
          'script',
606
          'noscript',
607
          'iframe',
608
          'noframes',
609
          'noembed',
610
          'title',
611
          'style',
612
          'textarea',
613
          'xmp'
614
        ], tag);
615
      };
616
      const getLanguage = element => isElement(element) ? getOpt(element, 'lang') : Optional.none();
617
      return {
618
        up: constant({
619
          selector: ancestor,
620
          closest: closest,
621
          predicate: ancestor$1,
622
          all: parents
623
        }),
624
        down: constant({
625
          selector: descendants,
626
          predicate: descendants$1
627
        }),
628
        styles: constant({
629
          get: get$1,
630
          getRaw: getRaw,
631
          set: set$1,
632
          remove: remove$1
633
        }),
634
        attrs: constant({
635
          get: get$2,
636
          set: set$2,
637
          remove: remove$2,
638
          copyTo: copyAttributesTo
639
        }),
640
        insert: constant({
641
          before: before,
642
          after: after$1,
643
          afterAll: after,
644
          append: append$1,
645
          appendAll: append,
646
          prepend: prepend,
647
          wrap: wrap
648
        }),
649
        remove: constant({
650
          unwrap: unwrap,
651
          remove: remove
652
        }),
653
        create: constant({
654
          nu: SugarElement.fromTag,
655
          clone: clone$1,
656
          text: SugarElement.fromText
657
        }),
658
        query: constant({
659
          comparePosition,
660
          prevSibling: prevSibling,
661
          nextSibling: nextSibling
662
        }),
663
        property: constant({
664
          children: children,
665
          name: name,
666
          parent: parent,
667
          document,
668
          isText: isText,
669
          isComment: isComment,
670
          isElement: isElement,
671
          isSpecial,
672
          getLanguage,
673
          getText: get,
674
          setText: set,
675
          isBoundary,
676
          isEmptyTag,
677
          isNonEditable
678
        }),
679
        eq: eq,
680
        is: is$1
681
      };
682
    };
683
 
684
    const point = (element, offset) => ({
685
      element,
686
      offset
687
    });
688
 
689
    const scan = (universe, element, direction) => {
690
      if (universe.property().isText(element) && universe.property().getText(element).trim().length === 0 || universe.property().isComment(element)) {
691
        return direction(element).bind(elem => {
692
          return scan(universe, elem, direction).orThunk(() => {
693
            return Optional.some(elem);
694
          });
695
        });
696
      } else {
697
        return Optional.none();
698
      }
699
    };
700
    const toEnd = (universe, element) => {
701
      if (universe.property().isText(element)) {
702
        return universe.property().getText(element).length;
703
      }
704
      const children = universe.property().children(element);
705
      return children.length;
706
    };
707
    const freefallRtl$2 = (universe, element) => {
708
      const candidate = scan(universe, element, universe.query().prevSibling).getOr(element);
709
      if (universe.property().isText(candidate)) {
710
        return point(candidate, toEnd(universe, candidate));
711
      }
712
      const children = universe.property().children(candidate);
713
      return children.length > 0 ? freefallRtl$2(universe, children[children.length - 1]) : point(candidate, toEnd(universe, candidate));
714
    };
715
 
716
    const freefallRtl$1 = freefallRtl$2;
717
 
718
    const universe = DomUniverse();
719
    const freefallRtl = element => {
720
      return freefallRtl$1(universe, element);
721
    };
722
 
723
    const fireToggleAccordionEvent = (editor, element, state) => editor.dispatch('ToggledAccordion', {
724
      element,
725
      state
726
    });
727
    const fireToggleAllAccordionsEvent = (editor, elements, state) => editor.dispatch('ToggledAllAccordions', {
728
      elements,
729
      state
730
    });
731
 
732
    const accordionTag = 'details';
733
    const accordionDetailsClass = 'mce-accordion';
734
    const accordionSummaryClass = 'mce-accordion-summary';
735
    const accordionBodyWrapperClass = 'mce-accordion-body';
736
    const accordionBodyWrapperTag = 'div';
737
 
738
    var global$3 = tinymce.util.Tools.resolve('tinymce.util.Tools');
739
 
740
    const isSummary = node => (node === null || node === void 0 ? void 0 : node.nodeName) === 'SUMMARY';
741
    const isDetails = node => (node === null || node === void 0 ? void 0 : node.nodeName) === 'DETAILS';
742
    const isOpen = details => details.hasAttribute('open');
743
    const isInSummary = editor => {
744
      const node = editor.selection.getNode();
745
      return isSummary(node) || Boolean(editor.dom.getParent(node, isSummary));
746
    };
747
    const isAtDetailsStart = editor => {
748
      const rng = editor.selection.getRng();
749
      return isDetails(rng.startContainer) && rng.collapsed && rng.startOffset === 0;
750
    };
751
    const isInsertAllowed = editor => !isInSummary(editor) && editor.dom.isEditable(editor.selection.getNode());
752
    const getSelectedDetails = editor => Optional.from(editor.dom.getParent(editor.selection.getNode(), isDetails));
753
    const isDetailsSelected = editor => getSelectedDetails(editor).isSome();
754
    const insertBogus = element => {
755
      element.innerHTML = '<br data-mce-bogus="1" />';
756
      return element;
757
    };
758
    const createParagraph = editor => insertBogus(editor.dom.create('p'));
759
    const createSummary = editor => insertBogus(editor.dom.create('summary'));
760
    const insertAndSelectParagraphAfter = (editor, target) => {
761
      const paragraph = createParagraph(editor);
762
      target.insertAdjacentElement('afterend', paragraph);
763
      editor.selection.setCursorLocation(paragraph, 0);
764
    };
765
    const normalizeContent = (editor, accordion) => {
766
      if (isSummary(accordion === null || accordion === void 0 ? void 0 : accordion.lastChild)) {
767
        const paragraph = createParagraph(editor);
768
        accordion.appendChild(paragraph);
769
        editor.selection.setCursorLocation(paragraph, 0);
770
      }
771
    };
772
    const normalizeSummary = (editor, accordion) => {
773
      if (!isSummary(accordion === null || accordion === void 0 ? void 0 : accordion.firstChild)) {
774
        const summary = createSummary(editor);
775
        accordion.prepend(summary);
776
        editor.selection.setCursorLocation(summary, 0);
777
      }
778
    };
779
    const normalizeAccordion = editor => accordion => {
780
      normalizeContent(editor, accordion);
781
      normalizeSummary(editor, accordion);
782
    };
783
    const normalizeDetails = editor => {
784
      global$3.each(global$3.grep(editor.dom.select('details', editor.getBody())), normalizeAccordion(editor));
785
    };
786
 
787
    const insertAccordion = editor => {
788
      if (!isInsertAllowed(editor)) {
789
        return;
790
      }
791
      const editorBody = SugarElement.fromDom(editor.getBody());
792
      const uid = generate('acc');
793
      const summaryText = editor.dom.encode(editor.selection.getRng().toString() || editor.translate('Accordion summary...'));
794
      const bodyText = editor.dom.encode(editor.translate('Accordion body...'));
795
      const accordionSummaryHtml = `<summary class="${ accordionSummaryClass }">${ summaryText }</summary>`;
796
      const accordionBodyHtml = `<${ accordionBodyWrapperTag } class="${ accordionBodyWrapperClass }"><p>${ bodyText }</p></${ accordionBodyWrapperTag }>`;
797
      editor.undoManager.transact(() => {
798
        editor.insertContent([
799
          `<details data-mce-id="${ uid }" class="${ accordionDetailsClass }" open="open">`,
800
          accordionSummaryHtml,
801
          accordionBodyHtml,
802
          `</details>`
803
        ].join(''));
804
        descendant(editorBody, `[data-mce-id="${ uid }"]`).each(detailsElm => {
805
          remove$2(detailsElm, 'data-mce-id');
806
          descendant(detailsElm, `summary`).each(summaryElm => {
807
            const rng = editor.dom.createRng();
808
            const des = freefallRtl(summaryElm);
809
            rng.setStart(des.element.dom, des.offset);
810
            rng.setEnd(des.element.dom, des.offset);
811
            editor.selection.setRng(rng);
812
          });
813
        });
814
      });
815
    };
816
    const toggleDetailsElement = (details, state) => {
817
      const shouldOpen = state !== null && state !== void 0 ? state : !isOpen(details);
818
      if (shouldOpen) {
819
        details.setAttribute('open', 'open');
820
      } else {
821
        details.removeAttribute('open');
822
      }
823
      return shouldOpen;
824
    };
825
    const toggleAccordion = (editor, state) => {
826
      getSelectedDetails(editor).each(details => {
827
        fireToggleAccordionEvent(editor, details, toggleDetailsElement(details, state));
828
      });
829
    };
830
    const removeAccordion = editor => {
831
      getSelectedDetails(editor).each(details => {
832
        const {nextSibling} = details;
833
        if (nextSibling) {
834
          editor.selection.select(nextSibling, true);
835
          editor.selection.collapse(true);
836
        } else {
837
          insertAndSelectParagraphAfter(editor, details);
838
        }
839
        details.remove();
840
      });
841
    };
842
    const toggleAllAccordions = (editor, state) => {
843
      const accordions = Array.from(editor.getBody().querySelectorAll('details'));
844
      if (accordions.length === 0) {
845
        return;
846
      }
847
      each$1(accordions, accordion => toggleDetailsElement(accordion, state !== null && state !== void 0 ? state : !isOpen(accordion)));
848
      fireToggleAllAccordionsEvent(editor, accordions, state);
849
    };
850
 
851
    const register$1 = editor => {
852
      editor.addCommand('InsertAccordion', () => insertAccordion(editor));
853
      editor.addCommand('ToggleAccordion', (_ui, value) => toggleAccordion(editor, value));
854
      editor.addCommand('ToggleAllAccordions', (_ui, value) => toggleAllAccordions(editor, value));
855
      editor.addCommand('RemoveAccordion', () => removeAccordion(editor));
856
    };
857
 
858
    var global$2 = tinymce.util.Tools.resolve('tinymce.html.Node');
859
 
860
    const getClassList = node => {
861
      var _a, _b;
862
      return (_b = (_a = node.attr('class')) === null || _a === void 0 ? void 0 : _a.split(' ')) !== null && _b !== void 0 ? _b : [];
863
    };
864
    const addClasses = (node, classes) => {
865
      const classListSet = new Set([
866
        ...getClassList(node),
867
        ...classes
868
      ]);
869
      const newClassList = Array.from(classListSet);
870
      if (newClassList.length > 0) {
871
        node.attr('class', newClassList.join(' '));
872
      }
873
    };
874
    const removeClasses = (node, classes) => {
875
      const newClassList = filter(getClassList(node), clazz => !classes.has(clazz));
876
      node.attr('class', newClassList.length > 0 ? newClassList.join(' ') : null);
877
    };
878
    const isAccordionDetailsNode = node => node.name === accordionTag && contains(getClassList(node), accordionDetailsClass);
879
    const isAccordionBodyWrapperNode = node => node.name === accordionBodyWrapperTag && contains(getClassList(node), accordionBodyWrapperClass);
880
    const getAccordionChildren = accordionNode => {
881
      const children = accordionNode.children();
882
      let summaryNode;
883
      let wrapperNode;
884
      const otherNodes = [];
885
      for (let i = 0; i < children.length; i++) {
886
        const child = children[i];
887
        if (child.name === 'summary' && isNullable(summaryNode)) {
888
          summaryNode = child;
889
        } else if (isAccordionBodyWrapperNode(child) && isNullable(wrapperNode)) {
890
          wrapperNode = child;
891
        } else {
892
          otherNodes.push(child);
893
        }
894
      }
895
      return {
896
        summaryNode,
897
        wrapperNode,
898
        otherNodes
899
      };
900
    };
901
    const padInputNode = node => {
902
      const br = new global$2('br', 1);
903
      br.attr('data-mce-bogus', '1');
904
      node.empty();
905
      node.append(br);
906
    };
907
    const setup$2 = editor => {
908
      editor.on('PreInit', () => {
909
        const {serializer, parser} = editor;
910
        parser.addNodeFilter(accordionTag, nodes => {
911
          for (let i = 0; i < nodes.length; i++) {
912
            const node = nodes[i];
913
            if (isAccordionDetailsNode(node)) {
914
              const accordionNode = node;
915
              const {summaryNode, wrapperNode, otherNodes} = getAccordionChildren(accordionNode);
916
              const hasSummaryNode = isNonNullable(summaryNode);
917
              const newSummaryNode = hasSummaryNode ? summaryNode : new global$2('summary', 1);
918
              if (isNullable(newSummaryNode.firstChild)) {
919
                padInputNode(newSummaryNode);
920
              }
921
              addClasses(newSummaryNode, [accordionSummaryClass]);
922
              if (!hasSummaryNode) {
923
                if (isNonNullable(accordionNode.firstChild)) {
924
                  accordionNode.insert(newSummaryNode, accordionNode.firstChild, true);
925
                } else {
926
                  accordionNode.append(newSummaryNode);
927
                }
928
              }
929
              const hasWrapperNode = isNonNullable(wrapperNode);
930
              const newWrapperNode = hasWrapperNode ? wrapperNode : new global$2(accordionBodyWrapperTag, 1);
931
              newWrapperNode.attr('data-mce-bogus', '1');
932
              addClasses(newWrapperNode, [accordionBodyWrapperClass]);
933
              if (otherNodes.length > 0) {
934
                for (let j = 0; j < otherNodes.length; j++) {
935
                  const otherNode = otherNodes[j];
936
                  newWrapperNode.append(otherNode);
937
                }
938
              }
939
              if (isNullable(newWrapperNode.firstChild)) {
940
                const pNode = new global$2('p', 1);
941
                padInputNode(pNode);
942
                newWrapperNode.append(pNode);
943
              }
944
              if (!hasWrapperNode) {
945
                accordionNode.append(newWrapperNode);
946
              }
947
            }
948
          }
949
        });
950
        serializer.addNodeFilter(accordionTag, nodes => {
951
          const summaryClassRemoveSet = new Set([accordionSummaryClass]);
952
          for (let i = 0; i < nodes.length; i++) {
953
            const node = nodes[i];
954
            if (isAccordionDetailsNode(node)) {
955
              const accordionNode = node;
956
              const {summaryNode, wrapperNode} = getAccordionChildren(accordionNode);
957
              if (isNonNullable(summaryNode)) {
958
                removeClasses(summaryNode, summaryClassRemoveSet);
959
              }
960
              if (isNonNullable(wrapperNode)) {
961
                wrapperNode.unwrap();
962
              }
963
            }
964
          }
965
        });
966
      });
967
    };
968
 
969
    var global$1 = tinymce.util.Tools.resolve('tinymce.util.VK');
970
 
971
    const setupEnterKeyInSummary = editor => {
972
      editor.on('keydown', event => {
973
        if (!event.shiftKey && event.keyCode === global$1.ENTER && isInSummary(editor) || isAtDetailsStart(editor)) {
974
          event.preventDefault();
975
          editor.execCommand('ToggleAccordion');
976
        }
977
      });
978
    };
979
    const setup$1 = editor => {
980
      setupEnterKeyInSummary(editor);
981
      editor.on('ExecCommand', e => {
982
        const cmd = e.command.toLowerCase();
983
        if ((cmd === 'delete' || cmd === 'forwarddelete') && isDetailsSelected(editor)) {
984
          normalizeDetails(editor);
985
        }
986
      });
987
    };
988
 
989
    var global = tinymce.util.Tools.resolve('tinymce.Env');
990
 
991
    const setup = editor => {
992
      if (global.browser.isSafari()) {
993
        editor.on('click', e => {
994
          if (isSummary(e.target)) {
995
            const summary = e.target;
996
            const rng = editor.selection.getRng();
997
            if (rng.collapsed && rng.startContainer === summary.parentNode && rng.startOffset === 0) {
998
              editor.selection.setCursorLocation(summary, 0);
999
            }
1000
          }
1001
        });
1002
      }
1003
    };
1004
 
1005
    const onSetup = editor => buttonApi => {
1006
      const onNodeChange = () => buttonApi.setEnabled(isInsertAllowed(editor));
1007
      editor.on('NodeChange', onNodeChange);
1008
      return () => editor.off('NodeChange', onNodeChange);
1009
    };
1010
    const register = editor => {
1011
      const onAction = () => editor.execCommand('InsertAccordion');
1012
      editor.ui.registry.addButton('accordion', {
1013
        icon: 'accordion',
1014
        tooltip: 'Insert accordion',
1015
        onSetup: onSetup(editor),
1016
        onAction
1017
      });
1018
      editor.ui.registry.addMenuItem('accordion', {
1019
        icon: 'accordion',
1020
        text: 'Accordion',
1021
        onSetup: onSetup(editor),
1022
        onAction
1023
      });
1024
      editor.ui.registry.addToggleButton('accordiontoggle', {
1025
        icon: 'accordion-toggle',
1026
        tooltip: 'Toggle accordion',
1027
        onAction: () => editor.execCommand('ToggleAccordion')
1028
      });
1029
      editor.ui.registry.addToggleButton('accordionremove', {
1030
        icon: 'remove',
1031
        tooltip: 'Delete accordion',
1032
        onAction: () => editor.execCommand('RemoveAccordion')
1033
      });
1034
      editor.ui.registry.addContextToolbar('accordion', {
1035
        predicate: accordion => editor.dom.is(accordion, 'details') && editor.getBody().contains(accordion) && editor.dom.isEditable(accordion.parentNode),
1036
        items: 'accordiontoggle accordionremove',
1037
        scope: 'node',
1038
        position: 'node'
1039
      });
1040
    };
1041
 
1042
    var Plugin = () => {
1043
      global$4.add('accordion', editor => {
1044
        register(editor);
1045
        register$1(editor);
1046
        setup$1(editor);
1047
        setup$2(editor);
1048
        setup(editor);
1049
      });
1050
    };
1051
 
1052
    Plugin();
1053
 
1054
})();