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$3 = tinymce.util.Tools.resolve('tinymce.PluginManager');
9
 
10
    const hasProto = (v, constructor, predicate) => {
11
      var _a;
12
      if (predicate(v, constructor.prototype)) {
13
        return true;
14
      } else {
15
        return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
16
      }
17
    };
18
    const typeOf = x => {
19
      const t = typeof x;
20
      if (x === null) {
21
        return 'null';
22
      } else if (t === 'object' && Array.isArray(x)) {
23
        return 'array';
24
      } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
25
        return 'string';
26
      } else {
27
        return t;
28
      }
29
    };
30
    const isType$1 = type => value => typeOf(value) === type;
31
    const isSimpleType = type => value => typeof value === type;
32
    const eq$1 = t => a => t === a;
33
    const isString = isType$1('string');
34
    const isArray = isType$1('array');
35
    const isBoolean = isSimpleType('boolean');
36
    const isUndefined = eq$1(undefined);
37
    const isNullable = a => a === null || a === undefined;
38
    const isNonNullable = a => !isNullable(a);
39
    const isFunction = isSimpleType('function');
40
    const isNumber = isSimpleType('number');
41
 
42
    const noop = () => {
43
    };
44
    const compose1 = (fbc, fab) => a => fbc(fab(a));
45
    const constant = value => {
46
      return () => {
47
        return value;
48
      };
49
    };
50
    const identity = x => {
51
      return x;
52
    };
53
    const tripleEquals = (a, b) => {
54
      return a === b;
55
    };
56
    function curry(fn, ...initialArgs) {
57
      return (...restArgs) => {
58
        const all = initialArgs.concat(restArgs);
59
        return fn.apply(null, all);
60
      };
61
    }
62
    const call = f => {
63
      f();
64
    };
65
    const never = constant(false);
66
    const always = constant(true);
67
 
68
    class Optional {
69
      constructor(tag, value) {
70
        this.tag = tag;
71
        this.value = value;
72
      }
73
      static some(value) {
74
        return new Optional(true, value);
75
      }
76
      static none() {
77
        return Optional.singletonNone;
78
      }
79
      fold(onNone, onSome) {
80
        if (this.tag) {
81
          return onSome(this.value);
82
        } else {
83
          return onNone();
84
        }
85
      }
86
      isSome() {
87
        return this.tag;
88
      }
89
      isNone() {
90
        return !this.tag;
91
      }
92
      map(mapper) {
93
        if (this.tag) {
94
          return Optional.some(mapper(this.value));
95
        } else {
96
          return Optional.none();
97
        }
98
      }
99
      bind(binder) {
100
        if (this.tag) {
101
          return binder(this.value);
102
        } else {
103
          return Optional.none();
104
        }
105
      }
106
      exists(predicate) {
107
        return this.tag && predicate(this.value);
108
      }
109
      forall(predicate) {
110
        return !this.tag || predicate(this.value);
111
      }
112
      filter(predicate) {
113
        if (!this.tag || predicate(this.value)) {
114
          return this;
115
        } else {
116
          return Optional.none();
117
        }
118
      }
119
      getOr(replacement) {
120
        return this.tag ? this.value : replacement;
121
      }
122
      or(replacement) {
123
        return this.tag ? this : replacement;
124
      }
125
      getOrThunk(thunk) {
126
        return this.tag ? this.value : thunk();
127
      }
128
      orThunk(thunk) {
129
        return this.tag ? this : thunk();
130
      }
131
      getOrDie(message) {
132
        if (!this.tag) {
133
          throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
134
        } else {
135
          return this.value;
136
        }
137
      }
138
      static from(value) {
139
        return isNonNullable(value) ? Optional.some(value) : Optional.none();
140
      }
141
      getOrNull() {
142
        return this.tag ? this.value : null;
143
      }
144
      getOrUndefined() {
145
        return this.value;
146
      }
147
      each(worker) {
148
        if (this.tag) {
149
          worker(this.value);
150
        }
151
      }
152
      toArray() {
153
        return this.tag ? [this.value] : [];
154
      }
155
      toString() {
156
        return this.tag ? `some(${ this.value })` : 'none()';
157
      }
158
    }
159
    Optional.singletonNone = new Optional(false);
160
 
161
    const keys = Object.keys;
162
    const hasOwnProperty = Object.hasOwnProperty;
163
    const each$1 = (obj, f) => {
164
      const props = keys(obj);
165
      for (let k = 0, len = props.length; k < len; k++) {
166
        const i = props[k];
167
        const x = obj[i];
168
        f(x, i);
169
      }
170
    };
171
    const objAcc = r => (x, i) => {
172
      r[i] = x;
173
    };
174
    const internalFilter = (obj, pred, onTrue, onFalse) => {
175
      each$1(obj, (x, i) => {
176
        (pred(x, i) ? onTrue : onFalse)(x, i);
177
      });
178
    };
179
    const filter$1 = (obj, pred) => {
180
      const t = {};
181
      internalFilter(obj, pred, objAcc(t), noop);
182
      return t;
183
    };
184
    const mapToArray = (obj, f) => {
185
      const r = [];
186
      each$1(obj, (value, name) => {
187
        r.push(f(value, name));
188
      });
189
      return r;
190
    };
191
    const values = obj => {
192
      return mapToArray(obj, identity);
193
    };
194
    const size = obj => {
195
      return keys(obj).length;
196
    };
197
    const get$4 = (obj, key) => {
198
      return has(obj, key) ? Optional.from(obj[key]) : Optional.none();
199
    };
200
    const has = (obj, key) => hasOwnProperty.call(obj, key);
201
    const hasNonNullableKey = (obj, key) => has(obj, key) && obj[key] !== undefined && obj[key] !== null;
202
    const isEmpty$1 = r => {
203
      for (const x in r) {
204
        if (hasOwnProperty.call(r, x)) {
205
          return false;
206
        }
207
      }
208
      return true;
209
    };
210
 
211
    const nativeIndexOf = Array.prototype.indexOf;
212
    const nativePush = Array.prototype.push;
213
    const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
214
    const contains = (xs, x) => rawIndexOf(xs, x) > -1;
215
    const exists = (xs, pred) => {
216
      for (let i = 0, len = xs.length; i < len; i++) {
217
        const x = xs[i];
218
        if (pred(x, i)) {
219
          return true;
220
        }
221
      }
222
      return false;
223
    };
224
    const range = (num, f) => {
225
      const r = [];
226
      for (let i = 0; i < num; i++) {
227
        r.push(f(i));
228
      }
229
      return r;
230
    };
231
    const map = (xs, f) => {
232
      const len = xs.length;
233
      const r = new Array(len);
234
      for (let i = 0; i < len; i++) {
235
        const x = xs[i];
236
        r[i] = f(x, i);
237
      }
238
      return r;
239
    };
240
    const each = (xs, f) => {
241
      for (let i = 0, len = xs.length; i < len; i++) {
242
        const x = xs[i];
243
        f(x, i);
244
      }
245
    };
246
    const eachr = (xs, f) => {
247
      for (let i = xs.length - 1; i >= 0; i--) {
248
        const x = xs[i];
249
        f(x, i);
250
      }
251
    };
252
    const partition = (xs, pred) => {
253
      const pass = [];
254
      const fail = [];
255
      for (let i = 0, len = xs.length; i < len; i++) {
256
        const x = xs[i];
257
        const arr = pred(x, i) ? pass : fail;
258
        arr.push(x);
259
      }
260
      return {
261
        pass,
262
        fail
263
      };
264
    };
265
    const filter = (xs, pred) => {
266
      const r = [];
267
      for (let i = 0, len = xs.length; i < len; i++) {
268
        const x = xs[i];
269
        if (pred(x, i)) {
270
          r.push(x);
271
        }
272
      }
273
      return r;
274
    };
275
    const foldr = (xs, f, acc) => {
276
      eachr(xs, (x, i) => {
277
        acc = f(acc, x, i);
278
      });
279
      return acc;
280
    };
281
    const foldl = (xs, f, acc) => {
282
      each(xs, (x, i) => {
283
        acc = f(acc, x, i);
284
      });
285
      return acc;
286
    };
287
    const findUntil = (xs, pred, until) => {
288
      for (let i = 0, len = xs.length; i < len; i++) {
289
        const x = xs[i];
290
        if (pred(x, i)) {
291
          return Optional.some(x);
292
        } else if (until(x, i)) {
293
          break;
294
        }
295
      }
296
      return Optional.none();
297
    };
298
    const find = (xs, pred) => {
299
      return findUntil(xs, pred, never);
300
    };
301
    const flatten$1 = xs => {
302
      const r = [];
303
      for (let i = 0, len = xs.length; i < len; ++i) {
304
        if (!isArray(xs[i])) {
305
          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
306
        }
307
        nativePush.apply(r, xs[i]);
308
      }
309
      return r;
310
    };
311
    const bind = (xs, f) => flatten$1(map(xs, f));
312
    const forall = (xs, pred) => {
313
      for (let i = 0, len = xs.length; i < len; ++i) {
314
        const x = xs[i];
315
        if (pred(x, i) !== true) {
316
          return false;
317
        }
318
      }
319
      return true;
320
    };
321
    const mapToObject = (xs, f) => {
322
      const r = {};
323
      for (let i = 0, len = xs.length; i < len; i++) {
324
        const x = xs[i];
325
        r[String(x)] = f(x, i);
326
      }
327
      return r;
328
    };
329
    const get$3 = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
330
    const head = xs => get$3(xs, 0);
331
    const last = xs => get$3(xs, xs.length - 1);
332
    const findMap = (arr, f) => {
333
      for (let i = 0; i < arr.length; i++) {
334
        const r = f(arr[i], i);
335
        if (r.isSome()) {
336
          return r;
337
        }
338
      }
339
      return Optional.none();
340
    };
341
 
342
    const COMMENT = 8;
343
    const DOCUMENT = 9;
344
    const DOCUMENT_FRAGMENT = 11;
345
    const ELEMENT = 1;
346
    const TEXT = 3;
347
 
348
    const fromHtml = (html, scope) => {
349
      const doc = scope || document;
350
      const div = doc.createElement('div');
351
      div.innerHTML = html;
352
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
353
        const message = 'HTML does not have a single root node';
354
        console.error(message, html);
355
        throw new Error(message);
356
      }
357
      return fromDom$1(div.childNodes[0]);
358
    };
359
    const fromTag = (tag, scope) => {
360
      const doc = scope || document;
361
      const node = doc.createElement(tag);
362
      return fromDom$1(node);
363
    };
364
    const fromText = (text, scope) => {
365
      const doc = scope || document;
366
      const node = doc.createTextNode(text);
367
      return fromDom$1(node);
368
    };
369
    const fromDom$1 = node => {
370
      if (node === null || node === undefined) {
371
        throw new Error('Node cannot be null or undefined');
372
      }
373
      return { dom: node };
374
    };
375
    const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$1);
376
    const SugarElement = {
377
      fromHtml,
378
      fromTag,
379
      fromText,
380
      fromDom: fromDom$1,
381
      fromPoint
382
    };
383
 
384
    const is$2 = (element, selector) => {
385
      const dom = element.dom;
386
      if (dom.nodeType !== ELEMENT) {
387
        return false;
388
      } else {
389
        const elem = dom;
390
        if (elem.matches !== undefined) {
391
          return elem.matches(selector);
392
        } else if (elem.msMatchesSelector !== undefined) {
393
          return elem.msMatchesSelector(selector);
394
        } else if (elem.webkitMatchesSelector !== undefined) {
395
          return elem.webkitMatchesSelector(selector);
396
        } else if (elem.mozMatchesSelector !== undefined) {
397
          return elem.mozMatchesSelector(selector);
398
        } else {
399
          throw new Error('Browser lacks native selectors');
400
        }
401
      }
402
    };
403
    const bypassSelector = dom => dom.nodeType !== ELEMENT && dom.nodeType !== DOCUMENT && dom.nodeType !== DOCUMENT_FRAGMENT || dom.childElementCount === 0;
404
    const all$1 = (selector, scope) => {
405
      const base = scope === undefined ? document : scope.dom;
406
      return bypassSelector(base) ? [] : map(base.querySelectorAll(selector), SugarElement.fromDom);
407
    };
408
    const one = (selector, scope) => {
409
      const base = scope === undefined ? document : scope.dom;
410
      return bypassSelector(base) ? Optional.none() : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
411
    };
412
 
413
    const eq = (e1, e2) => e1.dom === e2.dom;
414
    const is$1 = is$2;
415
 
416
    typeof window !== 'undefined' ? window : Function('return this;')();
417
 
418
    const name = element => {
419
      const r = element.dom.nodeName;
420
      return r.toLowerCase();
421
    };
422
    const type = element => element.dom.nodeType;
423
    const isType = t => element => type(element) === t;
424
    const isComment = element => type(element) === COMMENT || name(element) === '#comment';
425
    const isElement = isType(ELEMENT);
426
    const isText = isType(TEXT);
427
    const isDocument = isType(DOCUMENT);
428
    const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
429
    const isTag = tag => e => isElement(e) && name(e) === tag;
430
 
431
    const owner = element => SugarElement.fromDom(element.dom.ownerDocument);
432
    const documentOrOwner = dos => isDocument(dos) ? dos : owner(dos);
433
    const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
434
    const parents = (element, isRoot) => {
435
      const stop = isFunction(isRoot) ? isRoot : never;
436
      let dom = element.dom;
437
      const ret = [];
438
      while (dom.parentNode !== null && dom.parentNode !== undefined) {
439
        const rawParent = dom.parentNode;
440
        const p = SugarElement.fromDom(rawParent);
441
        ret.push(p);
442
        if (stop(p) === true) {
443
          break;
444
        } else {
445
          dom = rawParent;
446
        }
447
      }
448
      return ret;
449
    };
450
    const prevSibling = element => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
451
    const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
452
    const children$3 = element => map(element.dom.childNodes, SugarElement.fromDom);
453
    const child$3 = (element, index) => {
454
      const cs = element.dom.childNodes;
455
      return Optional.from(cs[index]).map(SugarElement.fromDom);
456
    };
457
    const firstChild = element => child$3(element, 0);
458
 
459
    const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
460
    const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
461
    const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
462
    const getShadowRoot = e => {
463
      const r = getRootNode(e);
464
      return isShadowRoot(r) ? Optional.some(r) : Optional.none();
465
    };
466
    const getShadowHost = e => SugarElement.fromDom(e.dom.host);
467
 
468
    const inBody = element => {
469
      const dom = isText(element) ? element.dom.parentNode : element.dom;
470
      if (dom === undefined || dom === null || dom.ownerDocument === null) {
471
        return false;
472
      }
473
      const doc = dom.ownerDocument;
474
      return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
475
    };
476
 
477
    var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
478
      if (is(scope, a)) {
479
        return Optional.some(scope);
480
      } else if (isFunction(isRoot) && isRoot(scope)) {
481
        return Optional.none();
482
      } else {
483
        return ancestor(scope, a, isRoot);
484
      }
485
    };
486
 
487
    const ancestor$1 = (scope, predicate, isRoot) => {
488
      let element = scope.dom;
489
      const stop = isFunction(isRoot) ? isRoot : never;
490
      while (element.parentNode) {
491
        element = element.parentNode;
492
        const el = SugarElement.fromDom(element);
493
        if (predicate(el)) {
494
          return Optional.some(el);
495
        } else if (stop(el)) {
496
          break;
497
        }
498
      }
499
      return Optional.none();
500
    };
501
    const closest$2 = (scope, predicate, isRoot) => {
502
      const is = (s, test) => test(s);
503
      return ClosestOrAncestor(is, ancestor$1, scope, predicate, isRoot);
504
    };
505
    const child$2 = (scope, predicate) => {
506
      const pred = node => predicate(SugarElement.fromDom(node));
507
      const result = find(scope.dom.childNodes, pred);
508
      return result.map(SugarElement.fromDom);
509
    };
510
 
511
    const ancestor = (scope, selector, isRoot) => ancestor$1(scope, e => is$2(e, selector), isRoot);
512
    const child$1 = (scope, selector) => child$2(scope, e => is$2(e, selector));
513
    const descendant = (scope, selector) => one(selector, scope);
514
    const closest$1 = (scope, selector, isRoot) => {
515
      const is = (element, selector) => is$2(element, selector);
516
      return ClosestOrAncestor(is, ancestor, scope, selector, isRoot);
517
    };
518
 
519
    const closest = target => closest$1(target, '[contenteditable]');
520
    const isEditable = (element, assumeEditable = false) => {
521
      if (inBody(element)) {
522
        return element.dom.isContentEditable;
523
      } else {
524
        return closest(element).fold(constant(assumeEditable), editable => getRaw$1(editable) === 'true');
525
      }
526
    };
527
    const getRaw$1 = element => element.dom.contentEditable;
528
 
529
    const getNodeName = elm => elm.nodeName.toLowerCase();
530
    const getBody = editor => SugarElement.fromDom(editor.getBody());
531
    const getIsRoot = editor => element => eq(element, getBody(editor));
532
    const removePxSuffix = size => size ? size.replace(/px$/, '') : '';
533
    const addPxSuffix = size => /^\d+(\.\d+)?$/.test(size) ? size + 'px' : size;
534
    const getSelectionStart = editor => SugarElement.fromDom(editor.selection.getStart());
535
    const getSelectionEnd = editor => SugarElement.fromDom(editor.selection.getEnd());
536
    const isInEditableContext = cell => closest$2(cell, isTag('table')).forall(isEditable);
537
 
538
    const children$2 = (scope, predicate) => filter(children$3(scope), predicate);
539
    const descendants$1 = (scope, predicate) => {
540
      let result = [];
541
      each(children$3(scope), x => {
542
        if (predicate(x)) {
543
          result = result.concat([x]);
544
        }
545
        result = result.concat(descendants$1(x, predicate));
546
      });
547
      return result;
548
    };
549
 
550
    const children$1 = (scope, selector) => children$2(scope, e => is$2(e, selector));
551
    const descendants = (scope, selector) => all$1(selector, scope);
552
 
553
    const rawSet = (dom, key, value) => {
554
      if (isString(value) || isBoolean(value) || isNumber(value)) {
555
        dom.setAttribute(key, value + '');
556
      } else {
557
        console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
558
        throw new Error('Attribute value was not simple');
559
      }
560
    };
561
    const set$2 = (element, key, value) => {
562
      rawSet(element.dom, key, value);
563
    };
564
    const setAll = (element, attrs) => {
565
      const dom = element.dom;
566
      each$1(attrs, (v, k) => {
567
        rawSet(dom, k, v);
568
      });
569
    };
570
    const get$2 = (element, key) => {
571
      const v = element.dom.getAttribute(key);
572
      return v === null ? undefined : v;
573
    };
574
    const getOpt = (element, key) => Optional.from(get$2(element, key));
575
    const remove$2 = (element, key) => {
576
      element.dom.removeAttribute(key);
577
    };
578
    const clone = element => foldl(element.dom.attributes, (acc, attr) => {
579
      acc[attr.name] = attr.value;
580
      return acc;
581
    }, {});
582
 
583
    const is = (lhs, rhs, comparator = tripleEquals) => lhs.exists(left => comparator(left, rhs));
584
    const cat = arr => {
585
      const r = [];
586
      const push = x => {
587
        r.push(x);
588
      };
589
      for (let i = 0; i < arr.length; i++) {
590
        arr[i].each(push);
591
      }
592
      return r;
593
    };
594
    const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
595
    const flatten = oot => oot.bind(identity);
596
    const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
597
 
598
    const removeFromStart = (str, numChars) => {
599
      return str.substring(numChars);
600
    };
601
 
602
    const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
603
    const removeLeading = (str, prefix) => {
604
      return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str;
605
    };
606
    const startsWith = (str, prefix) => {
607
      return checkRange(str, prefix, 0);
608
    };
609
    const blank = r => s => s.replace(r, '');
610
    const trim = blank(/^\s+|\s+$/g);
611
    const isNotEmpty = s => s.length > 0;
612
    const isEmpty = s => !isNotEmpty(s);
613
    const toInt = (value, radix = 10) => {
614
      const num = parseInt(value, radix);
615
      return isNaN(num) ? Optional.none() : Optional.some(num);
616
    };
617
    const toFloat = value => {
618
      const num = parseFloat(value);
619
      return isNaN(num) ? Optional.none() : Optional.some(num);
620
    };
621
 
622
    const isSupported = dom => dom.style !== undefined && isFunction(dom.style.getPropertyValue);
623
 
624
    const internalSet = (dom, property, value) => {
625
      if (!isString(value)) {
626
        console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
627
        throw new Error('CSS value must be a string: ' + value);
628
      }
629
      if (isSupported(dom)) {
630
        dom.style.setProperty(property, value);
631
      }
632
    };
633
    const internalRemove = (dom, property) => {
634
      if (isSupported(dom)) {
635
        dom.style.removeProperty(property);
636
      }
637
    };
638
    const set$1 = (element, property, value) => {
639
      const dom = element.dom;
640
      internalSet(dom, property, value);
641
    };
642
    const get$1 = (element, property) => {
643
      const dom = element.dom;
644
      const styles = window.getComputedStyle(dom);
645
      const r = styles.getPropertyValue(property);
646
      return r === '' && !inBody(element) ? getUnsafeProperty(dom, property) : r;
647
    };
648
    const getUnsafeProperty = (dom, property) => isSupported(dom) ? dom.style.getPropertyValue(property) : '';
649
    const getRaw = (element, property) => {
650
      const dom = element.dom;
651
      const raw = getUnsafeProperty(dom, property);
652
      return Optional.from(raw).filter(r => r.length > 0);
653
    };
654
    const remove$1 = (element, property) => {
655
      const dom = element.dom;
656
      internalRemove(dom, property);
657
      if (is(getOpt(element, 'style').map(trim), '')) {
658
        remove$2(element, 'style');
659
      }
660
    };
661
 
662
    const getAttrValue = (cell, name, fallback = 0) => getOpt(cell, name).map(value => parseInt(value, 10)).getOr(fallback);
663
 
664
    const firstLayer = (scope, selector) => {
665
      return filterFirstLayer(scope, selector, always);
666
    };
667
    const filterFirstLayer = (scope, selector, predicate) => {
668
      return bind(children$3(scope), x => {
669
        if (is$2(x, selector)) {
670
          return predicate(x) ? [x] : [];
671
        } else {
672
          return filterFirstLayer(x, selector, predicate);
673
        }
674
      });
675
    };
676
 
677
    const validSectionList = [
678
      'tfoot',
679
      'thead',
680
      'tbody',
681
      'colgroup'
682
    ];
683
    const isValidSection = parentName => contains(validSectionList, parentName);
684
    const grid = (rows, columns) => ({
685
      rows,
686
      columns
687
    });
688
    const detail = (element, rowspan, colspan) => ({
689
      element,
690
      rowspan,
691
      colspan
692
    });
693
    const extended = (element, rowspan, colspan, row, column, isLocked) => ({
694
      element,
695
      rowspan,
696
      colspan,
697
      row,
698
      column,
699
      isLocked
700
    });
701
    const rowdetail = (element, cells, section) => ({
702
      element,
703
      cells,
704
      section
705
    });
706
    const bounds = (startRow, startCol, finishRow, finishCol) => ({
707
      startRow,
708
      startCol,
709
      finishRow,
710
      finishCol
711
    });
712
    const columnext = (element, colspan, column) => ({
713
      element,
714
      colspan,
715
      column
716
    });
717
    const colgroup = (element, columns) => ({
718
      element,
719
      columns
720
    });
721
 
722
    const lookup = (tags, element, isRoot = never) => {
723
      if (isRoot(element)) {
724
        return Optional.none();
725
      }
726
      if (contains(tags, name(element))) {
727
        return Optional.some(element);
728
      }
729
      const isRootOrUpperTable = elm => is$2(elm, 'table') || isRoot(elm);
730
      return ancestor(element, tags.join(','), isRootOrUpperTable);
731
    };
732
    const cell = (element, isRoot) => lookup([
733
      'td',
734
      'th'
735
    ], element, isRoot);
736
    const cells = ancestor => firstLayer(ancestor, 'th,td');
737
    const columns = ancestor => {
738
      if (is$2(ancestor, 'colgroup')) {
739
        return children$1(ancestor, 'col');
740
      } else {
741
        return bind(columnGroups(ancestor), columnGroup => children$1(columnGroup, 'col'));
742
      }
743
    };
744
    const table = (element, isRoot) => closest$1(element, 'table', isRoot);
745
    const rows = ancestor => firstLayer(ancestor, 'tr');
746
    const columnGroups = ancestor => table(ancestor).fold(constant([]), table => children$1(table, 'colgroup'));
747
 
748
    const fromRowsOrColGroups = (elems, getSection) => map(elems, row => {
749
      if (name(row) === 'colgroup') {
750
        const cells = map(columns(row), column => {
751
          const colspan = getAttrValue(column, 'span', 1);
752
          return detail(column, 1, colspan);
753
        });
754
        return rowdetail(row, cells, 'colgroup');
755
      } else {
756
        const cells$1 = map(cells(row), cell => {
757
          const rowspan = getAttrValue(cell, 'rowspan', 1);
758
          const colspan = getAttrValue(cell, 'colspan', 1);
759
          return detail(cell, rowspan, colspan);
760
        });
761
        return rowdetail(row, cells$1, getSection(row));
762
      }
763
    });
764
    const getParentSection = group => parent(group).map(parent => {
765
      const parentName = name(parent);
766
      return isValidSection(parentName) ? parentName : 'tbody';
767
    }).getOr('tbody');
768
    const fromTable$1 = table => {
769
      const rows$1 = rows(table);
770
      const columnGroups$1 = columnGroups(table);
771
      const elems = [
772
        ...columnGroups$1,
773
        ...rows$1
774
      ];
775
      return fromRowsOrColGroups(elems, getParentSection);
776
    };
777
 
778
    const LOCKED_COL_ATTR = 'data-snooker-locked-cols';
779
    const getLockedColumnsFromTable = table => getOpt(table, LOCKED_COL_ATTR).bind(lockedColStr => Optional.from(lockedColStr.match(/\d+/g))).map(lockedCols => mapToObject(lockedCols, always));
780
 
781
    const key = (row, column) => {
782
      return row + ',' + column;
783
    };
784
    const getAt = (warehouse, row, column) => Optional.from(warehouse.access[key(row, column)]);
785
    const findItem = (warehouse, item, comparator) => {
786
      const filtered = filterItems(warehouse, detail => {
787
        return comparator(item, detail.element);
788
      });
789
      return filtered.length > 0 ? Optional.some(filtered[0]) : Optional.none();
790
    };
791
    const filterItems = (warehouse, predicate) => {
792
      const all = bind(warehouse.all, r => {
793
        return r.cells;
794
      });
795
      return filter(all, predicate);
796
    };
797
    const generateColumns = rowData => {
798
      const columnsGroup = {};
799
      let index = 0;
800
      each(rowData.cells, column => {
801
        const colspan = column.colspan;
802
        range(colspan, columnIndex => {
803
          const colIndex = index + columnIndex;
804
          columnsGroup[colIndex] = columnext(column.element, colspan, colIndex);
805
        });
806
        index += colspan;
807
      });
808
      return columnsGroup;
809
    };
810
    const generate$1 = list => {
811
      const access = {};
812
      const cells = [];
813
      const tableOpt = head(list).map(rowData => rowData.element).bind(table);
814
      const lockedColumns = tableOpt.bind(getLockedColumnsFromTable).getOr({});
815
      let maxRows = 0;
816
      let maxColumns = 0;
817
      let rowCount = 0;
818
      const {
819
        pass: colgroupRows,
820
        fail: rows
821
      } = partition(list, rowData => rowData.section === 'colgroup');
822
      each(rows, rowData => {
823
        const currentRow = [];
824
        each(rowData.cells, rowCell => {
825
          let start = 0;
826
          while (access[key(rowCount, start)] !== undefined) {
827
            start++;
828
          }
829
          const isLocked = hasNonNullableKey(lockedColumns, start.toString());
830
          const current = extended(rowCell.element, rowCell.rowspan, rowCell.colspan, rowCount, start, isLocked);
831
          for (let occupiedColumnPosition = 0; occupiedColumnPosition < rowCell.colspan; occupiedColumnPosition++) {
832
            for (let occupiedRowPosition = 0; occupiedRowPosition < rowCell.rowspan; occupiedRowPosition++) {
833
              const rowPosition = rowCount + occupiedRowPosition;
834
              const columnPosition = start + occupiedColumnPosition;
835
              const newpos = key(rowPosition, columnPosition);
836
              access[newpos] = current;
837
              maxColumns = Math.max(maxColumns, columnPosition + 1);
838
            }
839
          }
840
          currentRow.push(current);
841
        });
842
        maxRows++;
843
        cells.push(rowdetail(rowData.element, currentRow, rowData.section));
844
        rowCount++;
845
      });
846
      const {columns, colgroups} = last(colgroupRows).map(rowData => {
847
        const columns = generateColumns(rowData);
848
        const colgroup$1 = colgroup(rowData.element, values(columns));
849
        return {
850
          colgroups: [colgroup$1],
851
          columns
852
        };
853
      }).getOrThunk(() => ({
854
        colgroups: [],
855
        columns: {}
856
      }));
857
      const grid$1 = grid(maxRows, maxColumns);
858
      return {
859
        grid: grid$1,
860
        access,
861
        all: cells,
862
        columns,
863
        colgroups
864
      };
865
    };
866
    const fromTable = table => {
867
      const list = fromTable$1(table);
868
      return generate$1(list);
869
    };
870
    const justCells = warehouse => bind(warehouse.all, w => w.cells);
871
    const justColumns = warehouse => values(warehouse.columns);
872
    const hasColumns = warehouse => keys(warehouse.columns).length > 0;
873
    const getColumnAt = (warehouse, columnIndex) => Optional.from(warehouse.columns[columnIndex]);
874
    const Warehouse = {
875
      fromTable,
876
      generate: generate$1,
877
      getAt,
878
      findItem,
879
      filterItems,
880
      justCells,
881
      justColumns,
882
      hasColumns,
883
      getColumnAt
884
    };
885
 
886
    var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools');
887
 
888
    const getTDTHOverallStyle = (dom, elm, name) => {
889
      const cells = dom.select('td,th', elm);
890
      let firstChildStyle;
891
      for (let i = 0; i < cells.length; i++) {
892
        const currentStyle = dom.getStyle(cells[i], name);
893
        if (isUndefined(firstChildStyle)) {
894
          firstChildStyle = currentStyle;
895
        }
896
        if (firstChildStyle !== currentStyle) {
897
          return '';
898
        }
899
      }
900
      return firstChildStyle;
901
    };
902
    const setAlign = (editor, elm, name) => {
903
      global$2.each('left center right'.split(' '), align => {
904
        if (align !== name) {
905
          editor.formatter.remove('align' + align, {}, elm);
906
        }
907
      });
908
      if (name) {
909
        editor.formatter.apply('align' + name, {}, elm);
910
      }
911
    };
912
    const setVAlign = (editor, elm, name) => {
913
      global$2.each('top middle bottom'.split(' '), align => {
914
        if (align !== name) {
915
          editor.formatter.remove('valign' + align, {}, elm);
916
        }
917
      });
918
      if (name) {
919
        editor.formatter.apply('valign' + name, {}, elm);
920
      }
921
    };
922
 
923
    const fireTableModified = (editor, table, data) => {
924
      editor.dispatch('TableModified', {
925
        ...data,
926
        table
927
      });
928
    };
929
 
930
    const toNumber = (px, fallback) => toFloat(px).getOr(fallback);
931
    const getProp = (element, name, fallback) => toNumber(get$1(element, name), fallback);
932
    const calcContentBoxSize = (element, size, upper, lower) => {
933
      const paddingUpper = getProp(element, `padding-${ upper }`, 0);
934
      const paddingLower = getProp(element, `padding-${ lower }`, 0);
935
      const borderUpper = getProp(element, `border-${ upper }-width`, 0);
936
      const borderLower = getProp(element, `border-${ lower }-width`, 0);
937
      return size - paddingUpper - paddingLower - borderUpper - borderLower;
938
    };
939
    const getCalculatedWidth = (element, boxSizing) => {
940
      const dom = element.dom;
941
      const width = dom.getBoundingClientRect().width || dom.offsetWidth;
942
      return boxSizing === 'border-box' ? width : calcContentBoxSize(element, width, 'left', 'right');
943
    };
944
    const getInnerWidth = element => getCalculatedWidth(element, 'content-box');
945
 
946
    const getInner = getInnerWidth;
947
 
948
    var global$1 = tinymce.util.Tools.resolve('tinymce.Env');
949
 
950
    const defaultTableToolbar = 'tableprops tabledelete | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol';
951
    const defaultCellBorderWidths = range(5, i => {
952
      const size = `${ i + 1 }px`;
953
      return {
954
        title: size,
955
        value: size
956
      };
957
    });
958
    const defaultCellBorderStyles = map([
959
      'Solid',
960
      'Dotted',
961
      'Dashed',
962
      'Double',
963
      'Groove',
964
      'Ridge',
965
      'Inset',
966
      'Outset',
967
      'None',
968
      'Hidden'
969
    ], type => {
970
      return {
971
        title: type,
972
        value: type.toLowerCase()
973
      };
974
    });
975
    const defaultWidth = '100%';
976
    const getPixelForcedWidth = editor => {
977
      var _a;
978
      const dom = editor.dom;
979
      const parentBlock = (_a = dom.getParent(editor.selection.getStart(), dom.isBlock)) !== null && _a !== void 0 ? _a : editor.getBody();
980
      return getInner(SugarElement.fromDom(parentBlock)) + 'px';
981
    };
982
    const determineDefaultStyles = (editor, defaultStyles) => {
983
      if (isResponsiveForced(editor) || !shouldStyleWithCss(editor)) {
984
        return defaultStyles;
985
      } else if (isPixelsForced(editor)) {
986
        return {
987
          ...defaultStyles,
988
          width: getPixelForcedWidth(editor)
989
        };
990
      } else {
991
        return {
992
          ...defaultStyles,
993
          width: defaultWidth
994
        };
995
      }
996
    };
997
    const determineDefaultAttributes = (editor, defaultAttributes) => {
998
      if (isResponsiveForced(editor) || shouldStyleWithCss(editor)) {
999
        return defaultAttributes;
1000
      } else if (isPixelsForced(editor)) {
1001
        return {
1002
          ...defaultAttributes,
1003
          width: getPixelForcedWidth(editor)
1004
        };
1005
      } else {
1006
        return {
1007
          ...defaultAttributes,
1008
          width: defaultWidth
1009
        };
1010
      }
1011
    };
1012
    const option = name => editor => editor.options.get(name);
1013
    const register = editor => {
1014
      const registerOption = editor.options.register;
1015
      registerOption('table_border_widths', {
1016
        processor: 'object[]',
1017
        default: defaultCellBorderWidths
1018
      });
1019
      registerOption('table_border_styles', {
1020
        processor: 'object[]',
1021
        default: defaultCellBorderStyles
1022
      });
1023
      registerOption('table_cell_advtab', {
1024
        processor: 'boolean',
1025
        default: true
1026
      });
1027
      registerOption('table_row_advtab', {
1028
        processor: 'boolean',
1029
        default: true
1030
      });
1031
      registerOption('table_advtab', {
1032
        processor: 'boolean',
1033
        default: true
1034
      });
1035
      registerOption('table_appearance_options', {
1036
        processor: 'boolean',
1037
        default: true
1038
      });
1039
      registerOption('table_grid', {
1040
        processor: 'boolean',
1041
        default: !global$1.deviceType.isTouch()
1042
      });
1043
      registerOption('table_cell_class_list', {
1044
        processor: 'object[]',
1045
        default: []
1046
      });
1047
      registerOption('table_row_class_list', {
1048
        processor: 'object[]',
1049
        default: []
1050
      });
1051
      registerOption('table_class_list', {
1052
        processor: 'object[]',
1053
        default: []
1054
      });
1055
      registerOption('table_toolbar', {
1056
        processor: 'string',
1057
        default: defaultTableToolbar
1058
      });
1059
      registerOption('table_background_color_map', {
1060
        processor: 'object[]',
1061
        default: []
1062
      });
1063
      registerOption('table_border_color_map', {
1064
        processor: 'object[]',
1065
        default: []
1066
      });
1067
    };
1068
    const getTableSizingMode = option('table_sizing_mode');
1069
    const getTableBorderWidths = option('table_border_widths');
1070
    const getTableBorderStyles = option('table_border_styles');
1071
    const hasAdvancedCellTab = option('table_cell_advtab');
1072
    const hasAdvancedRowTab = option('table_row_advtab');
1073
    const hasAdvancedTableTab = option('table_advtab');
1074
    const hasAppearanceOptions = option('table_appearance_options');
1075
    const hasTableGrid = option('table_grid');
1076
    const shouldStyleWithCss = option('table_style_by_css');
1077
    const getCellClassList = option('table_cell_class_list');
1078
    const getRowClassList = option('table_row_class_list');
1079
    const getTableClassList = option('table_class_list');
1080
    const getToolbar = option('table_toolbar');
1081
    const getTableBackgroundColorMap = option('table_background_color_map');
1082
    const getTableBorderColorMap = option('table_border_color_map');
1083
    const isPixelsForced = editor => getTableSizingMode(editor) === 'fixed';
1084
    const isResponsiveForced = editor => getTableSizingMode(editor) === 'responsive';
1085
    const getDefaultStyles = editor => {
1086
      const options = editor.options;
1087
      const defaultStyles = options.get('table_default_styles');
1088
      return options.isSet('table_default_styles') ? defaultStyles : determineDefaultStyles(editor, defaultStyles);
1089
    };
1090
    const getDefaultAttributes = editor => {
1091
      const options = editor.options;
1092
      const defaultAttributes = options.get('table_default_attributes');
1093
      return options.isSet('table_default_attributes') ? defaultAttributes : determineDefaultAttributes(editor, defaultAttributes);
1094
    };
1095
 
1096
    const isWithin = (bounds, detail) => {
1097
      return detail.column >= bounds.startCol && detail.column + detail.colspan - 1 <= bounds.finishCol && detail.row >= bounds.startRow && detail.row + detail.rowspan - 1 <= bounds.finishRow;
1098
    };
1099
    const isRectangular = (warehouse, bounds) => {
1100
      let isRect = true;
1101
      const detailIsWithin = curry(isWithin, bounds);
1102
      for (let i = bounds.startRow; i <= bounds.finishRow; i++) {
1103
        for (let j = bounds.startCol; j <= bounds.finishCol; j++) {
1104
          isRect = isRect && Warehouse.getAt(warehouse, i, j).exists(detailIsWithin);
1105
        }
1106
      }
1107
      return isRect ? Optional.some(bounds) : Optional.none();
1108
    };
1109
 
1110
    const getBounds = (detailA, detailB) => {
1111
      return bounds(Math.min(detailA.row, detailB.row), Math.min(detailA.column, detailB.column), Math.max(detailA.row + detailA.rowspan - 1, detailB.row + detailB.rowspan - 1), Math.max(detailA.column + detailA.colspan - 1, detailB.column + detailB.colspan - 1));
1112
    };
1113
    const getAnyBox = (warehouse, startCell, finishCell) => {
1114
      const startCoords = Warehouse.findItem(warehouse, startCell, eq);
1115
      const finishCoords = Warehouse.findItem(warehouse, finishCell, eq);
1116
      return startCoords.bind(sc => {
1117
        return finishCoords.map(fc => {
1118
          return getBounds(sc, fc);
1119
        });
1120
      });
1121
    };
1122
    const getBox$1 = (warehouse, startCell, finishCell) => {
1123
      return getAnyBox(warehouse, startCell, finishCell).bind(bounds => {
1124
        return isRectangular(warehouse, bounds);
1125
      });
1126
    };
1127
 
1128
    const getBox = (table, first, last) => {
1129
      const warehouse = getWarehouse(table);
1130
      return getBox$1(warehouse, first, last);
1131
    };
1132
    const getWarehouse = Warehouse.fromTable;
1133
 
1134
    const before = (marker, element) => {
1135
      const parent$1 = parent(marker);
1136
      parent$1.each(v => {
1137
        v.dom.insertBefore(element.dom, marker.dom);
1138
      });
1139
    };
1140
    const after$1 = (marker, element) => {
1141
      const sibling = nextSibling(marker);
1142
      sibling.fold(() => {
1143
        const parent$1 = parent(marker);
1144
        parent$1.each(v => {
1145
          append$1(v, element);
1146
        });
1147
      }, v => {
1148
        before(v, element);
1149
      });
1150
    };
1151
    const prepend = (parent, element) => {
1152
      const firstChild$1 = firstChild(parent);
1153
      firstChild$1.fold(() => {
1154
        append$1(parent, element);
1155
      }, v => {
1156
        parent.dom.insertBefore(element.dom, v.dom);
1157
      });
1158
    };
1159
    const append$1 = (parent, element) => {
1160
      parent.dom.appendChild(element.dom);
1161
    };
1162
    const wrap = (element, wrapper) => {
1163
      before(element, wrapper);
1164
      append$1(wrapper, element);
1165
    };
1166
 
1167
    const after = (marker, elements) => {
1168
      each(elements, (x, i) => {
1169
        const e = i === 0 ? marker : elements[i - 1];
1170
        after$1(e, x);
1171
      });
1172
    };
1173
    const append = (parent, elements) => {
1174
      each(elements, x => {
1175
        append$1(parent, x);
1176
      });
1177
    };
1178
 
1179
    const remove = element => {
1180
      const dom = element.dom;
1181
      if (dom.parentNode !== null) {
1182
        dom.parentNode.removeChild(dom);
1183
      }
1184
    };
1185
    const unwrap = wrapper => {
1186
      const children = children$3(wrapper);
1187
      if (children.length > 0) {
1188
        after(wrapper, children);
1189
      }
1190
      remove(wrapper);
1191
    };
1192
 
1193
    const NodeValue = (is, name) => {
1194
      const get = element => {
1195
        if (!is(element)) {
1196
          throw new Error('Can only get ' + name + ' value of a ' + name + ' node');
1197
        }
1198
        return getOption(element).getOr('');
1199
      };
1200
      const getOption = element => is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
1201
      const set = (element, value) => {
1202
        if (!is(element)) {
1203
          throw new Error('Can only set raw ' + name + ' value of a ' + name + ' node');
1204
        }
1205
        element.dom.nodeValue = value;
1206
      };
1207
      return {
1208
        get,
1209
        getOption,
1210
        set
1211
      };
1212
    };
1213
 
1214
    const api = NodeValue(isText, 'text');
1215
    const get = element => api.get(element);
1216
    const set = (element, value) => api.set(element, value);
1217
 
1218
    var TagBoundaries = [
1219
      'body',
1220
      'p',
1221
      'div',
1222
      'article',
1223
      'aside',
1224
      'figcaption',
1225
      'figure',
1226
      'footer',
1227
      'header',
1228
      'nav',
1229
      'section',
1230
      'ol',
1231
      'ul',
1232
      'li',
1233
      'table',
1234
      'thead',
1235
      'tbody',
1236
      'tfoot',
1237
      'caption',
1238
      'tr',
1239
      'td',
1240
      'th',
1241
      'h1',
1242
      'h2',
1243
      'h3',
1244
      'h4',
1245
      'h5',
1246
      'h6',
1247
      'blockquote',
1248
      'pre',
1249
      'address'
1250
    ];
1251
 
1252
    var DomUniverse = () => {
1253
      const clone$1 = element => {
1254
        return SugarElement.fromDom(element.dom.cloneNode(false));
1255
      };
1256
      const document = element => documentOrOwner(element).dom;
1257
      const isBoundary = element => {
1258
        if (!isElement(element)) {
1259
          return false;
1260
        }
1261
        if (name(element) === 'body') {
1262
          return true;
1263
        }
1264
        return contains(TagBoundaries, name(element));
1265
      };
1266
      const isEmptyTag = element => {
1267
        if (!isElement(element)) {
1268
          return false;
1269
        }
1270
        return contains([
1271
          'br',
1272
          'img',
1273
          'hr',
1274
          'input'
1275
        ], name(element));
1276
      };
1277
      const isNonEditable = element => isElement(element) && get$2(element, 'contenteditable') === 'false';
1278
      const comparePosition = (element, other) => {
1279
        return element.dom.compareDocumentPosition(other.dom);
1280
      };
1281
      const copyAttributesTo = (source, destination) => {
1282
        const as = clone(source);
1283
        setAll(destination, as);
1284
      };
1285
      const isSpecial = element => {
1286
        const tag = name(element);
1287
        return contains([
1288
          'script',
1289
          'noscript',
1290
          'iframe',
1291
          'noframes',
1292
          'noembed',
1293
          'title',
1294
          'style',
1295
          'textarea',
1296
          'xmp'
1297
        ], tag);
1298
      };
1299
      const getLanguage = element => isElement(element) ? getOpt(element, 'lang') : Optional.none();
1300
      return {
1301
        up: constant({
1302
          selector: ancestor,
1303
          closest: closest$1,
1304
          predicate: ancestor$1,
1305
          all: parents
1306
        }),
1307
        down: constant({
1308
          selector: descendants,
1309
          predicate: descendants$1
1310
        }),
1311
        styles: constant({
1312
          get: get$1,
1313
          getRaw: getRaw,
1314
          set: set$1,
1315
          remove: remove$1
1316
        }),
1317
        attrs: constant({
1318
          get: get$2,
1319
          set: set$2,
1320
          remove: remove$2,
1321
          copyTo: copyAttributesTo
1322
        }),
1323
        insert: constant({
1324
          before: before,
1325
          after: after$1,
1326
          afterAll: after,
1327
          append: append$1,
1328
          appendAll: append,
1329
          prepend: prepend,
1330
          wrap: wrap
1331
        }),
1332
        remove: constant({
1333
          unwrap: unwrap,
1334
          remove: remove
1335
        }),
1336
        create: constant({
1337
          nu: SugarElement.fromTag,
1338
          clone: clone$1,
1339
          text: SugarElement.fromText
1340
        }),
1341
        query: constant({
1342
          comparePosition,
1343
          prevSibling: prevSibling,
1344
          nextSibling: nextSibling
1345
        }),
1346
        property: constant({
1347
          children: children$3,
1348
          name: name,
1349
          parent: parent,
1350
          document,
1351
          isText: isText,
1352
          isComment: isComment,
1353
          isElement: isElement,
1354
          isSpecial,
1355
          getLanguage,
1356
          getText: get,
1357
          setText: set,
1358
          isBoundary,
1359
          isEmptyTag,
1360
          isNonEditable
1361
        }),
1362
        eq: eq,
1363
        is: is$1
1364
      };
1365
    };
1366
 
1367
    const all = (universe, look, elements, f) => {
1368
      const head = elements[0];
1369
      const tail = elements.slice(1);
1370
      return f(universe, look, head, tail);
1371
    };
1372
    const oneAll = (universe, look, elements) => {
1373
      return elements.length > 0 ? all(universe, look, elements, unsafeOne) : Optional.none();
1374
    };
1375
    const unsafeOne = (universe, look, head, tail) => {
1376
      const start = look(universe, head);
1377
      return foldr(tail, (b, a) => {
1378
        const current = look(universe, a);
1379
        return commonElement(universe, b, current);
1380
      }, start);
1381
    };
1382
    const commonElement = (universe, start, end) => {
1383
      return start.bind(s => {
1384
        return end.filter(curry(universe.eq, s));
1385
      });
1386
    };
1387
 
1388
    const sharedOne$1 = oneAll;
1389
 
1390
    const universe = DomUniverse();
1391
    const sharedOne = (look, elements) => {
1392
      return sharedOne$1(universe, (_universe, element) => {
1393
        return look(element);
1394
      }, elements);
1395
    };
1396
 
1397
    const lookupTable = container => {
1398
      return ancestor(container, 'table');
1399
    };
1400
    const retrieve$1 = (container, selector) => {
1401
      const sels = descendants(container, selector);
1402
      return sels.length > 0 ? Optional.some(sels) : Optional.none();
1403
    };
1404
    const getEdges = (container, firstSelectedSelector, lastSelectedSelector) => {
1405
      return descendant(container, firstSelectedSelector).bind(first => {
1406
        return descendant(container, lastSelectedSelector).bind(last => {
1407
          return sharedOne(lookupTable, [
1408
            first,
1409
            last
1410
          ]).map(table => {
1411
            return {
1412
              first,
1413
              last,
1414
              table
1415
            };
1416
          });
1417
        });
1418
      });
1419
    };
1420
 
1421
    const retrieve = (container, selector) => {
1422
      return retrieve$1(container, selector);
1423
    };
1424
    const retrieveBox = (container, firstSelectedSelector, lastSelectedSelector) => {
1425
      return getEdges(container, firstSelectedSelector, lastSelectedSelector).bind(edges => {
1426
        const isRoot = ancestor => {
1427
          return eq(container, ancestor);
1428
        };
1429
        const sectionSelector = 'thead,tfoot,tbody,table';
1430
        const firstAncestor = ancestor(edges.first, sectionSelector, isRoot);
1431
        const lastAncestor = ancestor(edges.last, sectionSelector, isRoot);
1432
        return firstAncestor.bind(fA => {
1433
          return lastAncestor.bind(lA => {
1434
            return eq(fA, lA) ? getBox(edges.table, edges.first, edges.last) : Optional.none();
1435
          });
1436
        });
1437
      });
1438
    };
1439
 
1440
    const fromDom = nodes => map(nodes, SugarElement.fromDom);
1441
 
1442
    const strSelected = 'data-mce-selected';
1443
    const strSelectedSelector = 'td[' + strSelected + '],th[' + strSelected + ']';
1444
    const strFirstSelected = 'data-mce-first-selected';
1445
    const strFirstSelectedSelector = 'td[' + strFirstSelected + '],th[' + strFirstSelected + ']';
1446
    const strLastSelected = 'data-mce-last-selected';
1447
    const strLastSelectedSelector = 'td[' + strLastSelected + '],th[' + strLastSelected + ']';
1448
    const ephemera = {
1449
      selected: strSelected,
1450
      selectedSelector: strSelectedSelector,
1451
      firstSelected: strFirstSelected,
1452
      firstSelectedSelector: strFirstSelectedSelector,
1453
      lastSelected: strLastSelected,
1454
      lastSelectedSelector: strLastSelectedSelector
1455
    };
1456
 
1457
    const getSelectionCellFallback = element => table(element).bind(table => retrieve(table, ephemera.firstSelectedSelector)).fold(constant(element), cells => cells[0]);
1458
    const getSelectionFromSelector = selector => (initCell, isRoot) => {
1459
      const cellName = name(initCell);
1460
      const cell = cellName === 'col' || cellName === 'colgroup' ? getSelectionCellFallback(initCell) : initCell;
1461
      return closest$1(cell, selector, isRoot);
1462
    };
1463
    const getSelectionCellOrCaption = getSelectionFromSelector('th,td,caption');
1464
    const getSelectionCell = getSelectionFromSelector('th,td');
1465
    const getCellsFromSelection = editor => fromDom(editor.model.table.getSelectedCells());
1466
    const getRowsFromSelection = (selected, selector) => {
1467
      const cellOpt = getSelectionCell(selected);
1468
      const rowsOpt = cellOpt.bind(cell => table(cell)).map(table => rows(table));
1469
      return lift2(cellOpt, rowsOpt, (cell, rows) => filter(rows, row => exists(fromDom(row.dom.cells), rowCell => get$2(rowCell, selector) === '1' || eq(rowCell, cell)))).getOr([]);
1470
    };
1471
 
1472
    const verticalAlignValues = [
1473
      {
1474
        text: 'None',
1475
        value: ''
1476
      },
1477
      {
1478
        text: 'Top',
1479
        value: 'top'
1480
      },
1481
      {
1482
        text: 'Middle',
1483
        value: 'middle'
1484
      },
1485
      {
1486
        text: 'Bottom',
1487
        value: 'bottom'
1488
      }
1489
    ];
1490
 
1491
    const hexColour = value => ({ value: normalizeHex(value) });
1492
    const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
1493
    const longformRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
1494
    const isHexString = hex => shorthandRegex.test(hex) || longformRegex.test(hex);
1495
    const normalizeHex = hex => removeLeading(hex, '#').toUpperCase();
1496
    const fromString$1 = hex => isHexString(hex) ? Optional.some({ value: normalizeHex(hex) }) : Optional.none();
1497
    const toHex = component => {
1498
      const hex = component.toString(16);
1499
      return (hex.length === 1 ? '0' + hex : hex).toUpperCase();
1500
    };
1501
    const fromRgba = rgbaColour => {
1502
      const value = toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
1503
      return hexColour(value);
1504
    };
1505
 
1506
    const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
1507
    const rgbaRegex = /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
1508
    const rgbaColour = (red, green, blue, alpha) => ({
1509
      red,
1510
      green,
1511
      blue,
1512
      alpha
1513
    });
1514
    const fromStringValues = (red, green, blue, alpha) => {
1515
      const r = parseInt(red, 10);
1516
      const g = parseInt(green, 10);
1517
      const b = parseInt(blue, 10);
1518
      const a = parseFloat(alpha);
1519
      return rgbaColour(r, g, b, a);
1520
    };
1521
    const fromString = rgbaString => {
1522
      if (rgbaString === 'transparent') {
1523
        return Optional.some(rgbaColour(0, 0, 0, 0));
1524
      }
1525
      const rgbMatch = rgbRegex.exec(rgbaString);
1526
      if (rgbMatch !== null) {
1527
        return Optional.some(fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], '1'));
1528
      }
1529
      const rgbaMatch = rgbaRegex.exec(rgbaString);
1530
      if (rgbaMatch !== null) {
1531
        return Optional.some(fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4]));
1532
      }
1533
      return Optional.none();
1534
    };
1535
 
1536
    const anyToHex = color => fromString$1(color).orThunk(() => fromString(color).map(fromRgba)).getOrThunk(() => {
1537
      const canvas = document.createElement('canvas');
1538
      canvas.height = 1;
1539
      canvas.width = 1;
1540
      const canvasContext = canvas.getContext('2d');
1541
      canvasContext.clearRect(0, 0, canvas.width, canvas.height);
1542
      canvasContext.fillStyle = '#FFFFFF';
1543
      canvasContext.fillStyle = color;
1544
      canvasContext.fillRect(0, 0, 1, 1);
1545
      const rgba = canvasContext.getImageData(0, 0, 1, 1).data;
1546
      const r = rgba[0];
1547
      const g = rgba[1];
1548
      const b = rgba[2];
1549
      const a = rgba[3];
1550
      return fromRgba(rgbaColour(r, g, b, a));
1551
    });
1552
    const rgbaToHexString = color => fromString(color).map(fromRgba).map(h => '#' + h.value).getOr(color);
1553
 
1554
    const Cell = initial => {
1555
      let value = initial;
1556
      const get = () => {
1557
        return value;
1558
      };
1559
      const set = v => {
1560
        value = v;
1561
      };
1562
      return {
1563
        get,
1564
        set
1565
      };
1566
    };
1567
 
1568
    const singleton = doRevoke => {
1569
      const subject = Cell(Optional.none());
1570
      const revoke = () => subject.get().each(doRevoke);
1571
      const clear = () => {
1572
        revoke();
1573
        subject.set(Optional.none());
1574
      };
1575
      const isSet = () => subject.get().isSome();
1576
      const get = () => subject.get();
1577
      const set = s => {
1578
        revoke();
1579
        subject.set(Optional.some(s));
1580
      };
1581
      return {
1582
        clear,
1583
        isSet,
1584
        get,
1585
        set
1586
      };
1587
    };
1588
    const unbindable = () => singleton(s => s.unbind());
1589
 
1590
    const onSetupToggle = (editor, formatName, formatValue) => {
1591
      return api => {
1592
        const boundCallback = unbindable();
1593
        const isNone = isEmpty(formatValue);
1594
        const init = () => {
1595
          const selectedCells = getCellsFromSelection(editor);
1596
          const checkNode = cell => editor.formatter.match(formatName, { value: formatValue }, cell.dom, isNone);
1597
          if (isNone) {
1598
            api.setActive(!exists(selectedCells, checkNode));
1599
            boundCallback.set(editor.formatter.formatChanged(formatName, match => api.setActive(!match), true));
1600
          } else {
1601
            api.setActive(forall(selectedCells, checkNode));
1602
            boundCallback.set(editor.formatter.formatChanged(formatName, api.setActive, false, { value: formatValue }));
1603
          }
1604
        };
1605
        editor.initialized ? init() : editor.on('init', init);
1606
        return boundCallback.clear;
1607
      };
1608
    };
1609
    const isListGroup = item => hasNonNullableKey(item, 'menu');
1610
    const buildListItems = items => map(items, item => {
1611
      const text = item.text || item.title || '';
1612
      if (isListGroup(item)) {
1613
        return {
1614
          text,
1615
          items: buildListItems(item.menu)
1616
        };
1617
      } else {
1618
        return {
1619
          text,
1620
          value: item.value
1621
        };
1622
      }
1623
    });
1624
    const buildMenuItems = (editor, items, format, onAction) => map(items, item => {
1625
      const text = item.text || item.title;
1626
      if (isListGroup(item)) {
1627
        return {
1628
          type: 'nestedmenuitem',
1629
          text,
1630
          getSubmenuItems: () => buildMenuItems(editor, item.menu, format, onAction)
1631
        };
1632
      } else {
1633
        return {
1634
          text,
1635
          type: 'togglemenuitem',
1636
          onAction: () => onAction(item.value),
1637
          onSetup: onSetupToggle(editor, format, item.value)
1638
        };
1639
      }
1640
    });
1641
    const applyTableCellStyle = (editor, style) => value => {
1642
      editor.execCommand('mceTableApplyCellStyle', false, { [style]: value });
1643
    };
1644
    const filterNoneItem = list => bind(list, item => {
1645
      if (isListGroup(item)) {
1646
        return [{
1647
            ...item,
1648
            menu: filterNoneItem(item.menu)
1649
          }];
1650
      } else {
1651
        return isNotEmpty(item.value) ? [item] : [];
1652
      }
1653
    });
1654
    const generateMenuItemsCallback = (editor, items, format, onAction) => callback => callback(buildMenuItems(editor, items, format, onAction));
1655
    const buildColorMenu = (editor, colorList, style) => {
1656
      const colorMap = map(colorList, entry => ({
1657
        text: entry.title,
1658
        value: '#' + anyToHex(entry.value).value,
1659
        type: 'choiceitem'
1660
      }));
1661
      return [{
1662
          type: 'fancymenuitem',
1663
          fancytype: 'colorswatch',
1664
          initData: {
1665
            colors: colorMap.length > 0 ? colorMap : undefined,
1666
            allowCustomColors: false
1667
          },
1668
          onAction: data => {
1669
            const value = data.value === 'remove' ? '' : data.value;
1670
            editor.execCommand('mceTableApplyCellStyle', false, { [style]: value });
1671
          }
1672
        }];
1673
    };
1674
    const changeRowHeader = editor => () => {
1675
      const currentType = editor.queryCommandValue('mceTableRowType');
1676
      const newType = currentType === 'header' ? 'body' : 'header';
1677
      editor.execCommand('mceTableRowType', false, { type: newType });
1678
    };
1679
    const changeColumnHeader = editor => () => {
1680
      const currentType = editor.queryCommandValue('mceTableColType');
1681
      const newType = currentType === 'th' ? 'td' : 'th';
1682
      editor.execCommand('mceTableColType', false, { type: newType });
1683
    };
1684
 
1685
    const getClassList$1 = editor => {
1686
      const classes = buildListItems(getCellClassList(editor));
1687
      if (classes.length > 0) {
1688
        return Optional.some({
1689
          name: 'class',
1690
          type: 'listbox',
1691
          label: 'Class',
1692
          items: classes
1693
        });
1694
      }
1695
      return Optional.none();
1696
    };
1697
    const children = [
1698
      {
1699
        name: 'width',
1700
        type: 'input',
1701
        label: 'Width'
1702
      },
1703
      {
1704
        name: 'height',
1705
        type: 'input',
1706
        label: 'Height'
1707
      },
1708
      {
1709
        name: 'celltype',
1710
        type: 'listbox',
1711
        label: 'Cell type',
1712
        items: [
1713
          {
1714
            text: 'Cell',
1715
            value: 'td'
1716
          },
1717
          {
1718
            text: 'Header cell',
1719
            value: 'th'
1720
          }
1721
        ]
1722
      },
1723
      {
1724
        name: 'scope',
1725
        type: 'listbox',
1726
        label: 'Scope',
1727
        items: [
1728
          {
1729
            text: 'None',
1730
            value: ''
1731
          },
1732
          {
1733
            text: 'Row',
1734
            value: 'row'
1735
          },
1736
          {
1737
            text: 'Column',
1738
            value: 'col'
1739
          },
1740
          {
1741
            text: 'Row group',
1742
            value: 'rowgroup'
1743
          },
1744
          {
1745
            text: 'Column group',
1746
            value: 'colgroup'
1747
          }
1748
        ]
1749
      },
1750
      {
1751
        name: 'halign',
1752
        type: 'listbox',
1753
        label: 'Horizontal align',
1754
        items: [
1755
          {
1756
            text: 'None',
1757
            value: ''
1758
          },
1759
          {
1760
            text: 'Left',
1761
            value: 'left'
1762
          },
1763
          {
1764
            text: 'Center',
1765
            value: 'center'
1766
          },
1767
          {
1768
            text: 'Right',
1769
            value: 'right'
1770
          }
1771
        ]
1772
      },
1773
      {
1774
        name: 'valign',
1775
        type: 'listbox',
1776
        label: 'Vertical align',
1777
        items: verticalAlignValues
1778
      }
1779
    ];
1780
    const getItems$2 = editor => children.concat(getClassList$1(editor).toArray());
1781
 
1782
    const getAdvancedTab = (editor, dialogName) => {
1783
      const emptyBorderStyle = [{
1784
          text: 'Select...',
1785
          value: ''
1786
        }];
1787
      const advTabItems = [
1788
        {
1789
          name: 'borderstyle',
1790
          type: 'listbox',
1791
          label: 'Border style',
1792
          items: emptyBorderStyle.concat(buildListItems(getTableBorderStyles(editor)))
1793
        },
1794
        {
1795
          name: 'bordercolor',
1796
          type: 'colorinput',
1797
          label: 'Border color'
1798
        },
1799
        {
1800
          name: 'backgroundcolor',
1801
          type: 'colorinput',
1802
          label: 'Background color'
1803
        }
1804
      ];
1805
      const borderWidth = {
1806
        name: 'borderwidth',
1807
        type: 'input',
1808
        label: 'Border width'
1809
      };
1810
      const items = dialogName === 'cell' ? [borderWidth].concat(advTabItems) : advTabItems;
1811
      return {
1812
        title: 'Advanced',
1813
        name: 'advanced',
1814
        items
1815
      };
1816
    };
1817
 
1818
    const normal = (editor, element) => {
1819
      const dom = editor.dom;
1820
      const setAttrib = (attr, value) => {
1821
        dom.setAttrib(element, attr, value);
1822
      };
1823
      const setStyle = (prop, value) => {
1824
        dom.setStyle(element, prop, value);
1825
      };
1826
      const setFormat = (formatName, value) => {
1827
        if (value === '') {
1828
          editor.formatter.remove(formatName, { value: null }, element, true);
1829
        } else {
1830
          editor.formatter.apply(formatName, { value }, element);
1831
        }
1832
      };
1833
      return {
1834
        setAttrib,
1835
        setStyle,
1836
        setFormat
1837
      };
1838
    };
1839
    const DomModifier = { normal };
1840
 
1841
    const isHeaderCell = isTag('th');
1842
    const getRowHeaderType = (isHeaderRow, isHeaderCells) => {
1843
      if (isHeaderRow && isHeaderCells) {
1844
        return 'sectionCells';
1845
      } else if (isHeaderRow) {
1846
        return 'section';
1847
      } else {
1848
        return 'cells';
1849
      }
1850
    };
1851
    const getRowType$1 = row => {
1852
      const isHeaderRow = row.section === 'thead';
1853
      const isHeaderCells = is(findCommonCellType(row.cells), 'th');
1854
      if (row.section === 'tfoot') {
1855
        return { type: 'footer' };
1856
      } else if (isHeaderRow || isHeaderCells) {
1857
        return {
1858
          type: 'header',
1859
          subType: getRowHeaderType(isHeaderRow, isHeaderCells)
1860
        };
1861
      } else {
1862
        return { type: 'body' };
1863
      }
1864
    };
1865
    const findCommonCellType = cells => {
1866
      const headerCells = filter(cells, cell => isHeaderCell(cell.element));
1867
      if (headerCells.length === 0) {
1868
        return Optional.some('td');
1869
      } else if (headerCells.length === cells.length) {
1870
        return Optional.some('th');
1871
      } else {
1872
        return Optional.none();
1873
      }
1874
    };
1875
    const findCommonRowType = rows => {
1876
      const rowTypes = map(rows, row => getRowType$1(row).type);
1877
      const hasHeader = contains(rowTypes, 'header');
1878
      const hasFooter = contains(rowTypes, 'footer');
1879
      if (!hasHeader && !hasFooter) {
1880
        return Optional.some('body');
1881
      } else {
1882
        const hasBody = contains(rowTypes, 'body');
1883
        if (hasHeader && !hasBody && !hasFooter) {
1884
          return Optional.some('header');
1885
        } else if (!hasHeader && !hasBody && hasFooter) {
1886
          return Optional.some('footer');
1887
        } else {
1888
          return Optional.none();
1889
        }
1890
      }
1891
    };
1892
 
1893
    const cached = f => {
1894
      let called = false;
1895
      let r;
1896
      return (...args) => {
1897
        if (!called) {
1898
          called = true;
1899
          r = f.apply(null, args);
1900
        }
1901
        return r;
1902
      };
1903
    };
1904
 
1905
    const findInWarehouse = (warehouse, element) => findMap(warehouse.all, r => find(r.cells, e => eq(element, e.element)));
1906
    const extractCells = (warehouse, target, predicate) => {
1907
      const details = map(target.selection, cell$1 => {
1908
        return cell(cell$1).bind(lc => findInWarehouse(warehouse, lc)).filter(predicate);
1909
      });
1910
      const cells = cat(details);
1911
      return someIf(cells.length > 0, cells);
1912
    };
1913
    const onMergable = (_warehouse, target) => target.mergable;
1914
    const onUnmergable = (_warehouse, target) => target.unmergable;
1915
    const onCells = (warehouse, target) => extractCells(warehouse, target, always);
1916
    const isUnlockedTableCell = (warehouse, cell) => findInWarehouse(warehouse, cell).exists(detail => !detail.isLocked);
1917
    const allUnlocked = (warehouse, cells) => forall(cells, cell => isUnlockedTableCell(warehouse, cell));
1918
    const onUnlockedMergable = (warehouse, target) => onMergable(warehouse, target).filter(mergeable => allUnlocked(warehouse, mergeable.cells));
1919
    const onUnlockedUnmergable = (warehouse, target) => onUnmergable(warehouse, target).filter(cells => allUnlocked(warehouse, cells));
1920
 
1921
    const generate = cases => {
1922
      if (!isArray(cases)) {
1923
        throw new Error('cases must be an array');
1924
      }
1925
      if (cases.length === 0) {
1926
        throw new Error('there must be at least one case');
1927
      }
1928
      const constructors = [];
1929
      const adt = {};
1930
      each(cases, (acase, count) => {
1931
        const keys$1 = keys(acase);
1932
        if (keys$1.length !== 1) {
1933
          throw new Error('one and only one name per case');
1934
        }
1935
        const key = keys$1[0];
1936
        const value = acase[key];
1937
        if (adt[key] !== undefined) {
1938
          throw new Error('duplicate key detected:' + key);
1939
        } else if (key === 'cata') {
1940
          throw new Error('cannot have a case named cata (sorry)');
1941
        } else if (!isArray(value)) {
1942
          throw new Error('case arguments must be an array');
1943
        }
1944
        constructors.push(key);
1945
        adt[key] = (...args) => {
1946
          const argLength = args.length;
1947
          if (argLength !== value.length) {
1948
            throw new Error('Wrong number of arguments to case ' + key + '. Expected ' + value.length + ' (' + value + '), got ' + argLength);
1949
          }
1950
          const match = branches => {
1951
            const branchKeys = keys(branches);
1952
            if (constructors.length !== branchKeys.length) {
1953
              throw new Error('Wrong number of arguments to match. Expected: ' + constructors.join(',') + '\nActual: ' + branchKeys.join(','));
1954
            }
1955
            const allReqd = forall(constructors, reqKey => {
1956
              return contains(branchKeys, reqKey);
1957
            });
1958
            if (!allReqd) {
1959
              throw new Error('Not all branches were specified when using match. Specified: ' + branchKeys.join(', ') + '\nRequired: ' + constructors.join(', '));
1960
            }
1961
            return branches[key].apply(null, args);
1962
          };
1963
          return {
1964
            fold: (...foldArgs) => {
1965
              if (foldArgs.length !== cases.length) {
1966
                throw new Error('Wrong number of arguments to fold. Expected ' + cases.length + ', got ' + foldArgs.length);
1967
              }
1968
              const target = foldArgs[count];
1969
              return target.apply(null, args);
1970
            },
1971
            match,
1972
            log: label => {
1973
              console.log(label, {
1974
                constructors,
1975
                constructor: key,
1976
                params: args
1977
              });
1978
            }
1979
          };
1980
        };
1981
      });
1982
      return adt;
1983
    };
1984
    const Adt = { generate };
1985
 
1986
    const adt = Adt.generate([
1987
      { none: [] },
1988
      { only: ['index'] },
1989
      {
1990
        left: [
1991
          'index',
1992
          'next'
1993
        ]
1994
      },
1995
      {
1996
        middle: [
1997
          'prev',
1998
          'index',
1999
          'next'
2000
        ]
2001
      },
2002
      {
2003
        right: [
2004
          'prev',
2005
          'index'
2006
        ]
2007
      }
2008
    ]);
2009
    ({ ...adt });
2010
 
2011
    const opGetRowsType = (table, target) => {
2012
      const house = Warehouse.fromTable(table);
2013
      const details = onCells(house, target);
2014
      return details.bind(selectedCells => {
2015
        const lastSelectedCell = selectedCells[selectedCells.length - 1];
2016
        const minRowRange = selectedCells[0].row;
2017
        const maxRowRange = lastSelectedCell.row + lastSelectedCell.rowspan;
2018
        const selectedRows = house.all.slice(minRowRange, maxRowRange);
2019
        return findCommonRowType(selectedRows);
2020
      }).getOr('');
2021
    };
2022
    const getRowsType = opGetRowsType;
2023
 
2024
    const rgbToHex = value => startsWith(value, 'rgb') ? rgbaToHexString(value) : value;
2025
    const extractAdvancedStyles = elm => {
2026
      const element = SugarElement.fromDom(elm);
2027
      return {
2028
        borderwidth: getRaw(element, 'border-width').getOr(''),
2029
        borderstyle: getRaw(element, 'border-style').getOr(''),
2030
        bordercolor: getRaw(element, 'border-color').map(rgbToHex).getOr(''),
2031
        backgroundcolor: getRaw(element, 'background-color').map(rgbToHex).getOr('')
2032
      };
2033
    };
2034
    const getSharedValues = data => {
2035
      const baseData = data[0];
2036
      const comparisonData = data.slice(1);
2037
      each(comparisonData, items => {
2038
        each(keys(baseData), key => {
2039
          each$1(items, (itemValue, itemKey) => {
2040
            const comparisonValue = baseData[key];
2041
            if (comparisonValue !== '' && key === itemKey) {
2042
              if (comparisonValue !== itemValue) {
2043
                baseData[key] = '';
2044
              }
2045
            }
2046
          });
2047
        });
2048
      });
2049
      return baseData;
2050
    };
2051
    const getAlignment = (formats, formatName, editor, elm) => find(formats, name => !isUndefined(editor.formatter.matchNode(elm, formatName + name))).getOr('');
2052
    const getHAlignment = curry(getAlignment, [
2053
      'left',
2054
      'center',
2055
      'right'
2056
    ], 'align');
2057
    const getVAlignment = curry(getAlignment, [
2058
      'top',
2059
      'middle',
2060
      'bottom'
2061
    ], 'valign');
2062
    const extractDataFromSettings = (editor, hasAdvTableTab) => {
2063
      const style = getDefaultStyles(editor);
2064
      const attrs = getDefaultAttributes(editor);
2065
      const extractAdvancedStyleData = () => ({
2066
        borderstyle: get$4(style, 'border-style').getOr(''),
2067
        bordercolor: rgbToHex(get$4(style, 'border-color').getOr('')),
2068
        backgroundcolor: rgbToHex(get$4(style, 'background-color').getOr(''))
2069
      });
2070
      const defaultData = {
2071
        height: '',
2072
        width: '100%',
2073
        cellspacing: '',
2074
        cellpadding: '',
2075
        caption: false,
2076
        class: '',
2077
        align: '',
2078
        border: ''
2079
      };
2080
      const getBorder = () => {
2081
        const borderWidth = style['border-width'];
2082
        if (shouldStyleWithCss(editor) && borderWidth) {
2083
          return { border: borderWidth };
2084
        }
2085
        return get$4(attrs, 'border').fold(() => ({}), border => ({ border }));
2086
      };
2087
      const advStyle = hasAdvTableTab ? extractAdvancedStyleData() : {};
2088
      const getCellPaddingCellSpacing = () => {
2089
        const spacing = get$4(style, 'border-spacing').or(get$4(attrs, 'cellspacing')).fold(() => ({}), cellspacing => ({ cellspacing }));
2090
        const padding = get$4(style, 'border-padding').or(get$4(attrs, 'cellpadding')).fold(() => ({}), cellpadding => ({ cellpadding }));
2091
        return {
2092
          ...spacing,
2093
          ...padding
2094
        };
2095
      };
2096
      const data = {
2097
        ...defaultData,
2098
        ...style,
2099
        ...attrs,
2100
        ...advStyle,
2101
        ...getBorder(),
2102
        ...getCellPaddingCellSpacing()
2103
      };
2104
      return data;
2105
    };
2106
    const getRowType = elm => table(SugarElement.fromDom(elm)).map(table => {
2107
      const target = { selection: fromDom(elm.cells) };
2108
      return getRowsType(table, target);
2109
    }).getOr('');
2110
    const extractDataFromTableElement = (editor, elm, hasAdvTableTab) => {
2111
      const getBorder = (dom, elm) => {
2112
        const optBorderWidth = getRaw(SugarElement.fromDom(elm), 'border-width');
2113
        if (shouldStyleWithCss(editor) && optBorderWidth.isSome()) {
2114
          return optBorderWidth.getOr('');
2115
        }
2116
        return dom.getAttrib(elm, 'border') || getTDTHOverallStyle(editor.dom, elm, 'border-width') || getTDTHOverallStyle(editor.dom, elm, 'border') || '';
2117
      };
2118
      const dom = editor.dom;
2119
      const cellspacing = shouldStyleWithCss(editor) ? dom.getStyle(elm, 'border-spacing') || dom.getAttrib(elm, 'cellspacing') : dom.getAttrib(elm, 'cellspacing') || dom.getStyle(elm, 'border-spacing');
2120
      const cellpadding = shouldStyleWithCss(editor) ? getTDTHOverallStyle(dom, elm, 'padding') || dom.getAttrib(elm, 'cellpadding') : dom.getAttrib(elm, 'cellpadding') || getTDTHOverallStyle(dom, elm, 'padding');
2121
      return {
2122
        width: dom.getStyle(elm, 'width') || dom.getAttrib(elm, 'width'),
2123
        height: dom.getStyle(elm, 'height') || dom.getAttrib(elm, 'height'),
2124
        cellspacing: cellspacing !== null && cellspacing !== void 0 ? cellspacing : '',
2125
        cellpadding: cellpadding !== null && cellpadding !== void 0 ? cellpadding : '',
2126
        border: getBorder(dom, elm),
2127
        caption: !!dom.select('caption', elm)[0],
2128
        class: dom.getAttrib(elm, 'class', ''),
2129
        align: getHAlignment(editor, elm),
2130
        ...hasAdvTableTab ? extractAdvancedStyles(elm) : {}
2131
      };
2132
    };
2133
    const extractDataFromRowElement = (editor, elm, hasAdvancedRowTab) => {
2134
      const dom = editor.dom;
2135
      return {
2136
        height: dom.getStyle(elm, 'height') || dom.getAttrib(elm, 'height'),
2137
        class: dom.getAttrib(elm, 'class', ''),
2138
        type: getRowType(elm),
2139
        align: getHAlignment(editor, elm),
2140
        ...hasAdvancedRowTab ? extractAdvancedStyles(elm) : {}
2141
      };
2142
    };
2143
    const extractDataFromCellElement = (editor, cell, hasAdvancedCellTab, column) => {
2144
      const dom = editor.dom;
2145
      const colElm = column.getOr(cell);
2146
      const getStyle = (element, style) => dom.getStyle(element, style) || dom.getAttrib(element, style);
2147
      return {
2148
        width: getStyle(colElm, 'width'),
2149
        height: getStyle(cell, 'height'),
2150
        scope: dom.getAttrib(cell, 'scope'),
2151
        celltype: getNodeName(cell),
2152
        class: dom.getAttrib(cell, 'class', ''),
2153
        halign: getHAlignment(editor, cell),
2154
        valign: getVAlignment(editor, cell),
2155
        ...hasAdvancedCellTab ? extractAdvancedStyles(cell) : {}
2156
      };
2157
    };
2158
 
2159
    const getSelectedCells = (table, cells) => {
2160
      const warehouse = Warehouse.fromTable(table);
2161
      const allCells = Warehouse.justCells(warehouse);
2162
      const filtered = filter(allCells, cellA => exists(cells, cellB => eq(cellA.element, cellB)));
2163
      return map(filtered, cell => ({
2164
        element: cell.element.dom,
2165
        column: Warehouse.getColumnAt(warehouse, cell.column).map(col => col.element.dom)
2166
      }));
2167
    };
2168
    const updateSimpleProps$1 = (modifier, colModifier, data, shouldUpdate) => {
2169
      if (shouldUpdate('scope')) {
2170
        modifier.setAttrib('scope', data.scope);
2171
      }
2172
      if (shouldUpdate('class')) {
2173
        modifier.setAttrib('class', data.class);
2174
      }
2175
      if (shouldUpdate('height')) {
2176
        modifier.setStyle('height', addPxSuffix(data.height));
2177
      }
2178
      if (shouldUpdate('width')) {
2179
        colModifier.setStyle('width', addPxSuffix(data.width));
2180
      }
2181
    };
2182
    const updateAdvancedProps$1 = (modifier, data, shouldUpdate) => {
2183
      if (shouldUpdate('backgroundcolor')) {
2184
        modifier.setFormat('tablecellbackgroundcolor', data.backgroundcolor);
2185
      }
2186
      if (shouldUpdate('bordercolor')) {
2187
        modifier.setFormat('tablecellbordercolor', data.bordercolor);
2188
      }
2189
      if (shouldUpdate('borderstyle')) {
2190
        modifier.setFormat('tablecellborderstyle', data.borderstyle);
2191
      }
2192
      if (shouldUpdate('borderwidth')) {
2193
        modifier.setFormat('tablecellborderwidth', addPxSuffix(data.borderwidth));
2194
      }
2195
    };
2196
    const applyStyleData$1 = (editor, cells, data, wasChanged) => {
2197
      const isSingleCell = cells.length === 1;
2198
      each(cells, item => {
2199
        const cellElm = item.element;
2200
        const shouldOverrideCurrentValue = isSingleCell ? always : wasChanged;
2201
        const modifier = DomModifier.normal(editor, cellElm);
2202
        const colModifier = item.column.map(col => DomModifier.normal(editor, col)).getOr(modifier);
2203
        updateSimpleProps$1(modifier, colModifier, data, shouldOverrideCurrentValue);
2204
        if (hasAdvancedCellTab(editor)) {
2205
          updateAdvancedProps$1(modifier, data, shouldOverrideCurrentValue);
2206
        }
2207
        if (wasChanged('halign')) {
2208
          setAlign(editor, cellElm, data.halign);
2209
        }
2210
        if (wasChanged('valign')) {
2211
          setVAlign(editor, cellElm, data.valign);
2212
        }
2213
      });
2214
    };
2215
    const applyStructureData$1 = (editor, data) => {
2216
      editor.execCommand('mceTableCellType', false, {
2217
        type: data.celltype,
2218
        no_events: true
2219
      });
2220
    };
2221
    const applyCellData = (editor, cells, oldData, data) => {
2222
      const modifiedData = filter$1(data, (value, key) => oldData[key] !== value);
2223
      if (size(modifiedData) > 0 && cells.length >= 1) {
2224
        table(cells[0]).each(table => {
2225
          const selectedCells = getSelectedCells(table, cells);
2226
          const styleModified = size(filter$1(modifiedData, (_value, key) => key !== 'scope' && key !== 'celltype')) > 0;
2227
          const structureModified = has(modifiedData, 'celltype');
2228
          if (styleModified || has(modifiedData, 'scope')) {
2229
            applyStyleData$1(editor, selectedCells, data, curry(has, modifiedData));
2230
          }
2231
          if (structureModified) {
2232
            applyStructureData$1(editor, data);
2233
          }
2234
          fireTableModified(editor, table.dom, {
2235
            structure: structureModified,
2236
            style: styleModified
2237
          });
2238
        });
2239
      }
2240
    };
2241
    const onSubmitCellForm = (editor, cells, oldData, api) => {
2242
      const data = api.getData();
2243
      api.close();
2244
      editor.undoManager.transact(() => {
2245
        applyCellData(editor, cells, oldData, data);
2246
        editor.focus();
2247
      });
2248
    };
2249
    const getData$1 = (editor, cells) => {
2250
      const cellsData = table(cells[0]).map(table => map(getSelectedCells(table, cells), item => extractDataFromCellElement(editor, item.element, hasAdvancedCellTab(editor), item.column)));
2251
      return getSharedValues(cellsData.getOrDie());
2252
    };
2253
    const open$2 = editor => {
2254
      const cells = getCellsFromSelection(editor);
2255
      if (cells.length === 0) {
2256
        return;
2257
      }
2258
      const data = getData$1(editor, cells);
2259
      const dialogTabPanel = {
2260
        type: 'tabpanel',
2261
        tabs: [
2262
          {
2263
            title: 'General',
2264
            name: 'general',
2265
            items: getItems$2(editor)
2266
          },
2267
          getAdvancedTab(editor, 'cell')
2268
        ]
2269
      };
2270
      const dialogPanel = {
2271
        type: 'panel',
2272
        items: [{
2273
            type: 'grid',
2274
            columns: 2,
2275
            items: getItems$2(editor)
2276
          }]
2277
      };
2278
      editor.windowManager.open({
2279
        title: 'Cell Properties',
2280
        size: 'normal',
2281
        body: hasAdvancedCellTab(editor) ? dialogTabPanel : dialogPanel,
2282
        buttons: [
2283
          {
2284
            type: 'cancel',
2285
            name: 'cancel',
2286
            text: 'Cancel'
2287
          },
2288
          {
2289
            type: 'submit',
2290
            name: 'save',
2291
            text: 'Save',
2292
            primary: true
2293
          }
2294
        ],
2295
        initialData: data,
2296
        onSubmit: curry(onSubmitCellForm, editor, cells, data)
2297
      });
2298
    };
2299
 
2300
    const getClassList = editor => {
2301
      const classes = buildListItems(getRowClassList(editor));
2302
      if (classes.length > 0) {
2303
        return Optional.some({
2304
          name: 'class',
2305
          type: 'listbox',
2306
          label: 'Class',
2307
          items: classes
2308
        });
2309
      }
2310
      return Optional.none();
2311
    };
2312
    const formChildren = [
2313
      {
2314
        type: 'listbox',
2315
        name: 'type',
2316
        label: 'Row type',
2317
        items: [
2318
          {
2319
            text: 'Header',
2320
            value: 'header'
2321
          },
2322
          {
2323
            text: 'Body',
2324
            value: 'body'
2325
          },
2326
          {
2327
            text: 'Footer',
2328
            value: 'footer'
2329
          }
2330
        ]
2331
      },
2332
      {
2333
        type: 'listbox',
2334
        name: 'align',
2335
        label: 'Alignment',
2336
        items: [
2337
          {
2338
            text: 'None',
2339
            value: ''
2340
          },
2341
          {
2342
            text: 'Left',
2343
            value: 'left'
2344
          },
2345
          {
2346
            text: 'Center',
2347
            value: 'center'
2348
          },
2349
          {
2350
            text: 'Right',
2351
            value: 'right'
2352
          }
2353
        ]
2354
      },
2355
      {
2356
        label: 'Height',
2357
        name: 'height',
2358
        type: 'input'
2359
      }
2360
    ];
2361
    const getItems$1 = editor => formChildren.concat(getClassList(editor).toArray());
2362
 
2363
    const updateSimpleProps = (modifier, data, shouldUpdate) => {
2364
      if (shouldUpdate('class')) {
2365
        modifier.setAttrib('class', data.class);
2366
      }
2367
      if (shouldUpdate('height')) {
2368
        modifier.setStyle('height', addPxSuffix(data.height));
2369
      }
2370
    };
2371
    const updateAdvancedProps = (modifier, data, shouldUpdate) => {
2372
      if (shouldUpdate('backgroundcolor')) {
2373
        modifier.setStyle('background-color', data.backgroundcolor);
2374
      }
2375
      if (shouldUpdate('bordercolor')) {
2376
        modifier.setStyle('border-color', data.bordercolor);
2377
      }
2378
      if (shouldUpdate('borderstyle')) {
2379
        modifier.setStyle('border-style', data.borderstyle);
2380
      }
2381
    };
2382
    const applyStyleData = (editor, rows, data, wasChanged) => {
2383
      const isSingleRow = rows.length === 1;
2384
      const shouldOverrideCurrentValue = isSingleRow ? always : wasChanged;
2385
      each(rows, rowElm => {
2386
        const modifier = DomModifier.normal(editor, rowElm);
2387
        updateSimpleProps(modifier, data, shouldOverrideCurrentValue);
2388
        if (hasAdvancedRowTab(editor)) {
2389
          updateAdvancedProps(modifier, data, shouldOverrideCurrentValue);
2390
        }
2391
        if (wasChanged('align')) {
2392
          setAlign(editor, rowElm, data.align);
2393
        }
2394
      });
2395
    };
2396
    const applyStructureData = (editor, data) => {
2397
      editor.execCommand('mceTableRowType', false, {
2398
        type: data.type,
2399
        no_events: true
2400
      });
2401
    };
2402
    const applyRowData = (editor, rows, oldData, data) => {
2403
      const modifiedData = filter$1(data, (value, key) => oldData[key] !== value);
2404
      if (size(modifiedData) > 0) {
2405
        const typeModified = has(modifiedData, 'type');
2406
        const styleModified = typeModified ? size(modifiedData) > 1 : true;
2407
        if (styleModified) {
2408
          applyStyleData(editor, rows, data, curry(has, modifiedData));
2409
        }
2410
        if (typeModified) {
2411
          applyStructureData(editor, data);
2412
        }
2413
        table(SugarElement.fromDom(rows[0])).each(table => fireTableModified(editor, table.dom, {
2414
          structure: typeModified,
2415
          style: styleModified
2416
        }));
2417
      }
2418
    };
2419
    const onSubmitRowForm = (editor, rows, oldData, api) => {
2420
      const data = api.getData();
2421
      api.close();
2422
      editor.undoManager.transact(() => {
2423
        applyRowData(editor, rows, oldData, data);
2424
        editor.focus();
2425
      });
2426
    };
2427
    const open$1 = editor => {
2428
      const rows = getRowsFromSelection(getSelectionStart(editor), ephemera.selected);
2429
      if (rows.length === 0) {
2430
        return;
2431
      }
2432
      const rowsData = map(rows, rowElm => extractDataFromRowElement(editor, rowElm.dom, hasAdvancedRowTab(editor)));
2433
      const data = getSharedValues(rowsData);
2434
      const dialogTabPanel = {
2435
        type: 'tabpanel',
2436
        tabs: [
2437
          {
2438
            title: 'General',
2439
            name: 'general',
2440
            items: getItems$1(editor)
2441
          },
2442
          getAdvancedTab(editor, 'row')
2443
        ]
2444
      };
2445
      const dialogPanel = {
2446
        type: 'panel',
2447
        items: [{
2448
            type: 'grid',
2449
            columns: 2,
2450
            items: getItems$1(editor)
2451
          }]
2452
      };
2453
      editor.windowManager.open({
2454
        title: 'Row Properties',
2455
        size: 'normal',
2456
        body: hasAdvancedRowTab(editor) ? dialogTabPanel : dialogPanel,
2457
        buttons: [
2458
          {
2459
            type: 'cancel',
2460
            name: 'cancel',
2461
            text: 'Cancel'
2462
          },
2463
          {
2464
            type: 'submit',
2465
            name: 'save',
2466
            text: 'Save',
2467
            primary: true
2468
          }
2469
        ],
2470
        initialData: data,
2471
        onSubmit: curry(onSubmitRowForm, editor, map(rows, r => r.dom), data)
2472
      });
2473
    };
2474
 
2475
    const getItems = (editor, classes, insertNewTable) => {
2476
      const rowColCountItems = !insertNewTable ? [] : [
2477
        {
2478
          type: 'input',
2479
          name: 'cols',
2480
          label: 'Cols',
2481
          inputMode: 'numeric'
2482
        },
2483
        {
2484
          type: 'input',
2485
          name: 'rows',
2486
          label: 'Rows',
2487
          inputMode: 'numeric'
2488
        }
2489
      ];
2490
      const alwaysItems = [
2491
        {
2492
          type: 'input',
2493
          name: 'width',
2494
          label: 'Width'
2495
        },
2496
        {
2497
          type: 'input',
2498
          name: 'height',
2499
          label: 'Height'
2500
        }
2501
      ];
2502
      const appearanceItems = hasAppearanceOptions(editor) ? [
2503
        {
2504
          type: 'input',
2505
          name: 'cellspacing',
2506
          label: 'Cell spacing',
2507
          inputMode: 'numeric'
2508
        },
2509
        {
2510
          type: 'input',
2511
          name: 'cellpadding',
2512
          label: 'Cell padding',
2513
          inputMode: 'numeric'
2514
        },
2515
        {
2516
          type: 'input',
2517
          name: 'border',
2518
          label: 'Border width'
2519
        },
2520
        {
2521
          type: 'label',
2522
          label: 'Caption',
2523
          items: [{
2524
              type: 'checkbox',
2525
              name: 'caption',
2526
              label: 'Show caption'
2527
            }]
2528
        }
2529
      ] : [];
2530
      const alignmentItem = [{
2531
          type: 'listbox',
2532
          name: 'align',
2533
          label: 'Alignment',
2534
          items: [
2535
            {
2536
              text: 'None',
2537
              value: ''
2538
            },
2539
            {
2540
              text: 'Left',
2541
              value: 'left'
2542
            },
2543
            {
2544
              text: 'Center',
2545
              value: 'center'
2546
            },
2547
            {
2548
              text: 'Right',
2549
              value: 'right'
2550
            }
2551
          ]
2552
        }];
2553
      const classListItem = classes.length > 0 ? [{
2554
          type: 'listbox',
2555
          name: 'class',
2556
          label: 'Class',
2557
          items: classes
2558
        }] : [];
2559
      return rowColCountItems.concat(alwaysItems).concat(appearanceItems).concat(alignmentItem).concat(classListItem);
2560
    };
2561
 
2562
    const styleTDTH = (dom, elm, name, value) => {
2563
      if (elm.tagName === 'TD' || elm.tagName === 'TH') {
2564
        if (isString(name) && isNonNullable(value)) {
2565
          dom.setStyle(elm, name, value);
2566
        } else {
2567
          dom.setStyles(elm, name);
2568
        }
2569
      } else {
2570
        if (elm.children) {
2571
          for (let i = 0; i < elm.children.length; i++) {
2572
            styleTDTH(dom, elm.children[i], name, value);
2573
          }
2574
        }
2575
      }
2576
    };
2577
    const applyDataToElement = (editor, tableElm, data, shouldApplyOnCell) => {
2578
      const dom = editor.dom;
2579
      const attrs = {};
2580
      const styles = {};
2581
      const shouldStyleWithCss$1 = shouldStyleWithCss(editor);
2582
      const hasAdvancedTableTab$1 = hasAdvancedTableTab(editor);
2583
      if (!isUndefined(data.class)) {
2584
        attrs.class = data.class;
2585
      }
2586
      styles.height = addPxSuffix(data.height);
2587
      if (shouldStyleWithCss$1) {
2588
        styles.width = addPxSuffix(data.width);
2589
      } else if (dom.getAttrib(tableElm, 'width')) {
2590
        attrs.width = removePxSuffix(data.width);
2591
      }
2592
      if (shouldStyleWithCss$1) {
2593
        styles['border-width'] = addPxSuffix(data.border);
2594
        styles['border-spacing'] = addPxSuffix(data.cellspacing);
2595
      } else {
2596
        attrs.border = data.border;
2597
        attrs.cellpadding = data.cellpadding;
2598
        attrs.cellspacing = data.cellspacing;
2599
      }
2600
      if (shouldStyleWithCss$1 && tableElm.children) {
2601
        const cellStyles = {};
2602
        if (shouldApplyOnCell.border) {
2603
          cellStyles['border-width'] = addPxSuffix(data.border);
2604
        }
2605
        if (shouldApplyOnCell.cellpadding) {
2606
          cellStyles.padding = addPxSuffix(data.cellpadding);
2607
        }
2608
        if (hasAdvancedTableTab$1 && shouldApplyOnCell.bordercolor) {
2609
          cellStyles['border-color'] = data.bordercolor;
2610
        }
2611
        if (!isEmpty$1(cellStyles)) {
2612
          for (let i = 0; i < tableElm.children.length; i++) {
2613
            styleTDTH(dom, tableElm.children[i], cellStyles);
2614
          }
2615
        }
2616
      }
2617
      if (hasAdvancedTableTab$1) {
2618
        const advData = data;
2619
        styles['background-color'] = advData.backgroundcolor;
2620
        styles['border-color'] = advData.bordercolor;
2621
        styles['border-style'] = advData.borderstyle;
2622
      }
2623
      dom.setStyles(tableElm, {
2624
        ...getDefaultStyles(editor),
2625
        ...styles
2626
      });
2627
      dom.setAttribs(tableElm, {
2628
        ...getDefaultAttributes(editor),
2629
        ...attrs
2630
      });
2631
    };
2632
    const onSubmitTableForm = (editor, tableElm, oldData, api) => {
2633
      const dom = editor.dom;
2634
      const data = api.getData();
2635
      const modifiedData = filter$1(data, (value, key) => oldData[key] !== value);
2636
      api.close();
2637
      if (data.class === '') {
2638
        delete data.class;
2639
      }
2640
      editor.undoManager.transact(() => {
2641
        if (!tableElm) {
2642
          const cols = toInt(data.cols).getOr(1);
2643
          const rows = toInt(data.rows).getOr(1);
2644
          editor.execCommand('mceInsertTable', false, {
2645
            rows,
2646
            columns: cols
2647
          });
2648
          tableElm = getSelectionCell(getSelectionStart(editor), getIsRoot(editor)).bind(cell => table(cell, getIsRoot(editor))).map(table => table.dom).getOrDie();
2649
        }
2650
        if (size(modifiedData) > 0) {
2651
          const applicableCellProperties = {
2652
            border: has(modifiedData, 'border'),
2653
            bordercolor: has(modifiedData, 'bordercolor'),
2654
            cellpadding: has(modifiedData, 'cellpadding')
2655
          };
2656
          applyDataToElement(editor, tableElm, data, applicableCellProperties);
2657
          const captionElm = dom.select('caption', tableElm)[0];
2658
          if (captionElm && !data.caption || !captionElm && data.caption) {
2659
            editor.execCommand('mceTableToggleCaption');
2660
          }
2661
          setAlign(editor, tableElm, data.align);
2662
        }
2663
        editor.focus();
2664
        editor.addVisual();
2665
        if (size(modifiedData) > 0) {
2666
          const captionModified = has(modifiedData, 'caption');
2667
          const styleModified = captionModified ? size(modifiedData) > 1 : true;
2668
          fireTableModified(editor, tableElm, {
2669
            structure: captionModified,
2670
            style: styleModified
2671
          });
2672
        }
2673
      });
2674
    };
2675
    const open = (editor, insertNewTable) => {
2676
      const dom = editor.dom;
2677
      let tableElm;
2678
      let data = extractDataFromSettings(editor, hasAdvancedTableTab(editor));
2679
      if (insertNewTable) {
2680
        data.cols = '1';
2681
        data.rows = '1';
2682
        if (hasAdvancedTableTab(editor)) {
2683
          data.borderstyle = '';
2684
          data.bordercolor = '';
2685
          data.backgroundcolor = '';
2686
        }
2687
      } else {
2688
        tableElm = dom.getParent(editor.selection.getStart(), 'table', editor.getBody());
2689
        if (tableElm) {
2690
          data = extractDataFromTableElement(editor, tableElm, hasAdvancedTableTab(editor));
2691
        } else {
2692
          if (hasAdvancedTableTab(editor)) {
2693
            data.borderstyle = '';
2694
            data.bordercolor = '';
2695
            data.backgroundcolor = '';
2696
          }
2697
        }
2698
      }
2699
      const classes = buildListItems(getTableClassList(editor));
2700
      if (classes.length > 0) {
2701
        if (data.class) {
2702
          data.class = data.class.replace(/\s*mce\-item\-table\s*/g, '');
2703
        }
2704
      }
2705
      const generalPanel = {
2706
        type: 'grid',
2707
        columns: 2,
2708
        items: getItems(editor, classes, insertNewTable)
2709
      };
2710
      const nonAdvancedForm = () => ({
2711
        type: 'panel',
2712
        items: [generalPanel]
2713
      });
2714
      const advancedForm = () => ({
2715
        type: 'tabpanel',
2716
        tabs: [
2717
          {
2718
            title: 'General',
2719
            name: 'general',
2720
            items: [generalPanel]
2721
          },
2722
          getAdvancedTab(editor, 'table')
2723
        ]
2724
      });
2725
      const dialogBody = hasAdvancedTableTab(editor) ? advancedForm() : nonAdvancedForm();
2726
      editor.windowManager.open({
2727
        title: 'Table Properties',
2728
        size: 'normal',
2729
        body: dialogBody,
2730
        onSubmit: curry(onSubmitTableForm, editor, tableElm, data),
2731
        buttons: [
2732
          {
2733
            type: 'cancel',
2734
            name: 'cancel',
2735
            text: 'Cancel'
2736
          },
2737
          {
2738
            type: 'submit',
2739
            name: 'save',
2740
            text: 'Save',
2741
            primary: true
2742
          }
2743
        ],
2744
        initialData: data
2745
      });
2746
    };
2747
 
2748
    const registerCommands = editor => {
2749
      const runAction = f => {
2750
        if (isInEditableContext(getSelectionStart(editor))) {
2751
          f();
2752
        }
2753
      };
2754
      each$1({
2755
        mceTableProps: curry(open, editor, false),
2756
        mceTableRowProps: curry(open$1, editor),
2757
        mceTableCellProps: curry(open$2, editor),
2758
        mceInsertTableDialog: curry(open, editor, true)
2759
      }, (func, name) => editor.addCommand(name, () => runAction(func)));
2760
    };
2761
 
2762
    const child = (scope, selector) => child$1(scope, selector).isSome();
2763
 
2764
    const selection = identity;
2765
    const unmergable = selectedCells => {
2766
      const hasSpan = (elem, type) => getOpt(elem, type).exists(span => parseInt(span, 10) > 1);
2767
      const hasRowOrColSpan = elem => hasSpan(elem, 'rowspan') || hasSpan(elem, 'colspan');
2768
      return selectedCells.length > 0 && forall(selectedCells, hasRowOrColSpan) ? Optional.some(selectedCells) : Optional.none();
2769
    };
2770
    const mergable = (table, selectedCells, ephemera) => {
2771
      if (selectedCells.length <= 1) {
2772
        return Optional.none();
2773
      } else {
2774
        return retrieveBox(table, ephemera.firstSelectedSelector, ephemera.lastSelectedSelector).map(bounds => ({
2775
          bounds,
2776
          cells: selectedCells
2777
        }));
2778
      }
2779
    };
2780
 
2781
    const noMenu = cell => ({
2782
      element: cell,
2783
      mergable: Optional.none(),
2784
      unmergable: Optional.none(),
2785
      selection: [cell]
2786
    });
2787
    const forMenu = (selectedCells, table, cell) => ({
2788
      element: cell,
2789
      mergable: mergable(table, selectedCells, ephemera),
2790
      unmergable: unmergable(selectedCells),
2791
      selection: selection(selectedCells)
2792
    });
2793
 
2794
    const getSelectionTargets = editor => {
2795
      const targets = Cell(Optional.none());
2796
      const changeHandlers = Cell([]);
2797
      let selectionDetails = Optional.none();
2798
      const isCaption = isTag('caption');
2799
      const isDisabledForSelection = key => selectionDetails.forall(details => !details[key]);
2800
      const getStart = () => getSelectionCellOrCaption(getSelectionStart(editor), getIsRoot(editor));
2801
      const getEnd = () => getSelectionCellOrCaption(getSelectionEnd(editor), getIsRoot(editor));
2802
      const findTargets = () => getStart().bind(startCellOrCaption => flatten(lift2(table(startCellOrCaption), getEnd().bind(table), (startTable, endTable) => {
2803
        if (eq(startTable, endTable)) {
2804
          if (isCaption(startCellOrCaption)) {
2805
            return Optional.some(noMenu(startCellOrCaption));
2806
          } else {
2807
            return Optional.some(forMenu(getCellsFromSelection(editor), startTable, startCellOrCaption));
2808
          }
2809
        }
2810
        return Optional.none();
2811
      })));
2812
      const getExtractedDetails = targets => {
2813
        const tableOpt = table(targets.element);
2814
        return tableOpt.map(table => {
2815
          const warehouse = Warehouse.fromTable(table);
2816
          const selectedCells = onCells(warehouse, targets).getOr([]);
2817
          const locked = foldl(selectedCells, (acc, cell) => {
2818
            if (cell.isLocked) {
2819
              acc.onAny = true;
2820
              if (cell.column === 0) {
2821
                acc.onFirst = true;
2822
              } else if (cell.column + cell.colspan >= warehouse.grid.columns) {
2823
                acc.onLast = true;
2824
              }
2825
            }
2826
            return acc;
2827
          }, {
2828
            onAny: false,
2829
            onFirst: false,
2830
            onLast: false
2831
          });
2832
          return {
2833
            mergeable: onUnlockedMergable(warehouse, targets).isSome(),
2834
            unmergeable: onUnlockedUnmergable(warehouse, targets).isSome(),
2835
            locked
2836
          };
2837
        });
2838
      };
2839
      const resetTargets = () => {
2840
        targets.set(cached(findTargets)());
2841
        selectionDetails = targets.get().bind(getExtractedDetails);
2842
        each(changeHandlers.get(), call);
2843
      };
2844
      const setupHandler = handler => {
2845
        handler();
2846
        changeHandlers.set(changeHandlers.get().concat([handler]));
2847
        return () => {
2848
          changeHandlers.set(filter(changeHandlers.get(), h => h !== handler));
2849
        };
2850
      };
2851
      const onSetup = (api, isDisabled) => setupHandler(() => targets.get().fold(() => {
2852
        api.setEnabled(false);
2853
      }, targets => {
2854
        api.setEnabled(!isDisabled(targets) && editor.selection.isEditable());
2855
      }));
2856
      const onSetupWithToggle = (api, isDisabled, isActive) => setupHandler(() => targets.get().fold(() => {
2857
        api.setEnabled(false);
2858
        api.setActive(false);
2859
      }, targets => {
2860
        api.setEnabled(!isDisabled(targets) && editor.selection.isEditable());
2861
        api.setActive(isActive(targets));
2862
      }));
2863
      const isDisabledFromLocked = lockedDisable => selectionDetails.exists(details => details.locked[lockedDisable]);
2864
      const onSetupTable = api => onSetup(api, _ => false);
2865
      const onSetupCellOrRow = api => onSetup(api, targets => isCaption(targets.element));
2866
      const onSetupColumn = lockedDisable => api => onSetup(api, targets => isCaption(targets.element) || isDisabledFromLocked(lockedDisable));
2867
      const onSetupPasteable = getClipboardData => api => onSetup(api, targets => isCaption(targets.element) || getClipboardData().isNone());
2868
      const onSetupPasteableColumn = (getClipboardData, lockedDisable) => api => onSetup(api, targets => isCaption(targets.element) || getClipboardData().isNone() || isDisabledFromLocked(lockedDisable));
2869
      const onSetupMergeable = api => onSetup(api, _targets => isDisabledForSelection('mergeable'));
2870
      const onSetupUnmergeable = api => onSetup(api, _targets => isDisabledForSelection('unmergeable'));
2871
      const onSetupTableWithCaption = api => {
2872
        return onSetupWithToggle(api, never, targets => {
2873
          const tableOpt = table(targets.element, getIsRoot(editor));
2874
          return tableOpt.exists(table => child(table, 'caption'));
2875
        });
2876
      };
2877
      const onSetupTableHeaders = (command, headerType) => api => {
2878
        return onSetupWithToggle(api, targets => isCaption(targets.element), () => editor.queryCommandValue(command) === headerType);
2879
      };
2880
      const onSetupTableRowHeaders = onSetupTableHeaders('mceTableRowType', 'header');
2881
      const onSetupTableColumnHeaders = onSetupTableHeaders('mceTableColType', 'th');
2882
      editor.on('NodeChange ExecCommand TableSelectorChange', resetTargets);
2883
      return {
2884
        onSetupTable,
2885
        onSetupCellOrRow,
2886
        onSetupColumn,
2887
        onSetupPasteable,
2888
        onSetupPasteableColumn,
2889
        onSetupMergeable,
2890
        onSetupUnmergeable,
2891
        resetTargets,
2892
        onSetupTableWithCaption,
2893
        onSetupTableRowHeaders,
2894
        onSetupTableColumnHeaders,
2895
        targets: targets.get
2896
      };
2897
    };
2898
 
2899
    var global = tinymce.util.Tools.resolve('tinymce.FakeClipboard');
2900
 
2901
    const tableTypeBase = 'x-tinymce/dom-table-';
2902
    const tableTypeRow = tableTypeBase + 'rows';
2903
    const tableTypeColumn = tableTypeBase + 'columns';
2904
    const getData = type => {
2905
      var _a;
2906
      const items = (_a = global.read()) !== null && _a !== void 0 ? _a : [];
2907
      return findMap(items, item => Optional.from(item.getType(type)));
2908
    };
2909
    const getRows = () => getData(tableTypeRow);
2910
    const getColumns = () => getData(tableTypeColumn);
2911
 
2912
    const onSetupEditable$1 = editor => api => {
2913
      const nodeChanged = () => {
2914
        api.setEnabled(editor.selection.isEditable());
2915
      };
2916
      editor.on('NodeChange', nodeChanged);
2917
      nodeChanged();
2918
      return () => {
2919
        editor.off('NodeChange', nodeChanged);
2920
      };
2921
    };
2922
    const addButtons = (editor, selectionTargets) => {
2923
      editor.ui.registry.addMenuButton('table', {
2924
        tooltip: 'Table',
2925
        icon: 'table',
2926
        onSetup: onSetupEditable$1(editor),
2927
        fetch: callback => callback('inserttable | cell row column | advtablesort | tableprops deletetable')
2928
      });
2929
      const cmd = command => () => editor.execCommand(command);
2930
      const addButtonIfRegistered = (name, spec) => {
2931
        if (editor.queryCommandSupported(spec.command)) {
2932
          editor.ui.registry.addButton(name, {
2933
            ...spec,
2934
            onAction: isFunction(spec.onAction) ? spec.onAction : cmd(spec.command)
2935
          });
2936
        }
2937
      };
2938
      const addToggleButtonIfRegistered = (name, spec) => {
2939
        if (editor.queryCommandSupported(spec.command)) {
2940
          editor.ui.registry.addToggleButton(name, {
2941
            ...spec,
2942
            onAction: isFunction(spec.onAction) ? spec.onAction : cmd(spec.command)
2943
          });
2944
        }
2945
      };
2946
      addButtonIfRegistered('tableprops', {
2947
        tooltip: 'Table properties',
2948
        command: 'mceTableProps',
2949
        icon: 'table',
2950
        onSetup: selectionTargets.onSetupTable
2951
      });
2952
      addButtonIfRegistered('tabledelete', {
2953
        tooltip: 'Delete table',
2954
        command: 'mceTableDelete',
2955
        icon: 'table-delete-table',
2956
        onSetup: selectionTargets.onSetupTable
2957
      });
2958
      addButtonIfRegistered('tablecellprops', {
2959
        tooltip: 'Cell properties',
2960
        command: 'mceTableCellProps',
2961
        icon: 'table-cell-properties',
2962
        onSetup: selectionTargets.onSetupCellOrRow
2963
      });
2964
      addButtonIfRegistered('tablemergecells', {
2965
        tooltip: 'Merge cells',
2966
        command: 'mceTableMergeCells',
2967
        icon: 'table-merge-cells',
2968
        onSetup: selectionTargets.onSetupMergeable
2969
      });
2970
      addButtonIfRegistered('tablesplitcells', {
2971
        tooltip: 'Split cell',
2972
        command: 'mceTableSplitCells',
2973
        icon: 'table-split-cells',
2974
        onSetup: selectionTargets.onSetupUnmergeable
2975
      });
2976
      addButtonIfRegistered('tableinsertrowbefore', {
2977
        tooltip: 'Insert row before',
2978
        command: 'mceTableInsertRowBefore',
2979
        icon: 'table-insert-row-above',
2980
        onSetup: selectionTargets.onSetupCellOrRow
2981
      });
2982
      addButtonIfRegistered('tableinsertrowafter', {
2983
        tooltip: 'Insert row after',
2984
        command: 'mceTableInsertRowAfter',
2985
        icon: 'table-insert-row-after',
2986
        onSetup: selectionTargets.onSetupCellOrRow
2987
      });
2988
      addButtonIfRegistered('tabledeleterow', {
2989
        tooltip: 'Delete row',
2990
        command: 'mceTableDeleteRow',
2991
        icon: 'table-delete-row',
2992
        onSetup: selectionTargets.onSetupCellOrRow
2993
      });
2994
      addButtonIfRegistered('tablerowprops', {
2995
        tooltip: 'Row properties',
2996
        command: 'mceTableRowProps',
2997
        icon: 'table-row-properties',
2998
        onSetup: selectionTargets.onSetupCellOrRow
2999
      });
3000
      addButtonIfRegistered('tableinsertcolbefore', {
3001
        tooltip: 'Insert column before',
3002
        command: 'mceTableInsertColBefore',
3003
        icon: 'table-insert-column-before',
3004
        onSetup: selectionTargets.onSetupColumn('onFirst')
3005
      });
3006
      addButtonIfRegistered('tableinsertcolafter', {
3007
        tooltip: 'Insert column after',
3008
        command: 'mceTableInsertColAfter',
3009
        icon: 'table-insert-column-after',
3010
        onSetup: selectionTargets.onSetupColumn('onLast')
3011
      });
3012
      addButtonIfRegistered('tabledeletecol', {
3013
        tooltip: 'Delete column',
3014
        command: 'mceTableDeleteCol',
3015
        icon: 'table-delete-column',
3016
        onSetup: selectionTargets.onSetupColumn('onAny')
3017
      });
3018
      addButtonIfRegistered('tablecutrow', {
3019
        tooltip: 'Cut row',
3020
        command: 'mceTableCutRow',
3021
        icon: 'cut-row',
3022
        onSetup: selectionTargets.onSetupCellOrRow
3023
      });
3024
      addButtonIfRegistered('tablecopyrow', {
3025
        tooltip: 'Copy row',
3026
        command: 'mceTableCopyRow',
3027
        icon: 'duplicate-row',
3028
        onSetup: selectionTargets.onSetupCellOrRow
3029
      });
3030
      addButtonIfRegistered('tablepasterowbefore', {
3031
        tooltip: 'Paste row before',
3032
        command: 'mceTablePasteRowBefore',
3033
        icon: 'paste-row-before',
3034
        onSetup: selectionTargets.onSetupPasteable(getRows)
3035
      });
3036
      addButtonIfRegistered('tablepasterowafter', {
3037
        tooltip: 'Paste row after',
3038
        command: 'mceTablePasteRowAfter',
3039
        icon: 'paste-row-after',
3040
        onSetup: selectionTargets.onSetupPasteable(getRows)
3041
      });
3042
      addButtonIfRegistered('tablecutcol', {
3043
        tooltip: 'Cut column',
3044
        command: 'mceTableCutCol',
3045
        icon: 'cut-column',
3046
        onSetup: selectionTargets.onSetupColumn('onAny')
3047
      });
3048
      addButtonIfRegistered('tablecopycol', {
3049
        tooltip: 'Copy column',
3050
        command: 'mceTableCopyCol',
3051
        icon: 'duplicate-column',
3052
        onSetup: selectionTargets.onSetupColumn('onAny')
3053
      });
3054
      addButtonIfRegistered('tablepastecolbefore', {
3055
        tooltip: 'Paste column before',
3056
        command: 'mceTablePasteColBefore',
3057
        icon: 'paste-column-before',
3058
        onSetup: selectionTargets.onSetupPasteableColumn(getColumns, 'onFirst')
3059
      });
3060
      addButtonIfRegistered('tablepastecolafter', {
3061
        tooltip: 'Paste column after',
3062
        command: 'mceTablePasteColAfter',
3063
        icon: 'paste-column-after',
3064
        onSetup: selectionTargets.onSetupPasteableColumn(getColumns, 'onLast')
3065
      });
3066
      addButtonIfRegistered('tableinsertdialog', {
3067
        tooltip: 'Insert table',
3068
        command: 'mceInsertTableDialog',
3069
        icon: 'table',
3070
        onSetup: onSetupEditable$1(editor)
3071
      });
3072
      const tableClassList = filterNoneItem(getTableClassList(editor));
3073
      if (tableClassList.length !== 0 && editor.queryCommandSupported('mceTableToggleClass')) {
3074
        editor.ui.registry.addMenuButton('tableclass', {
3075
          icon: 'table-classes',
3076
          tooltip: 'Table styles',
3077
          fetch: generateMenuItemsCallback(editor, tableClassList, 'tableclass', value => editor.execCommand('mceTableToggleClass', false, value)),
3078
          onSetup: selectionTargets.onSetupTable
3079
        });
3080
      }
3081
      const tableCellClassList = filterNoneItem(getCellClassList(editor));
3082
      if (tableCellClassList.length !== 0 && editor.queryCommandSupported('mceTableCellToggleClass')) {
3083
        editor.ui.registry.addMenuButton('tablecellclass', {
3084
          icon: 'table-cell-classes',
3085
          tooltip: 'Cell styles',
3086
          fetch: generateMenuItemsCallback(editor, tableCellClassList, 'tablecellclass', value => editor.execCommand('mceTableCellToggleClass', false, value)),
3087
          onSetup: selectionTargets.onSetupCellOrRow
3088
        });
3089
      }
3090
      if (editor.queryCommandSupported('mceTableApplyCellStyle')) {
3091
        editor.ui.registry.addMenuButton('tablecellvalign', {
3092
          icon: 'vertical-align',
3093
          tooltip: 'Vertical align',
3094
          fetch: generateMenuItemsCallback(editor, verticalAlignValues, 'tablecellverticalalign', applyTableCellStyle(editor, 'vertical-align')),
3095
          onSetup: selectionTargets.onSetupCellOrRow
3096
        });
3097
        editor.ui.registry.addMenuButton('tablecellborderwidth', {
3098
          icon: 'border-width',
3099
          tooltip: 'Border width',
3100
          fetch: generateMenuItemsCallback(editor, getTableBorderWidths(editor), 'tablecellborderwidth', applyTableCellStyle(editor, 'border-width')),
3101
          onSetup: selectionTargets.onSetupCellOrRow
3102
        });
3103
        editor.ui.registry.addMenuButton('tablecellborderstyle', {
3104
          icon: 'border-style',
3105
          tooltip: 'Border style',
3106
          fetch: generateMenuItemsCallback(editor, getTableBorderStyles(editor), 'tablecellborderstyle', applyTableCellStyle(editor, 'border-style')),
3107
          onSetup: selectionTargets.onSetupCellOrRow
3108
        });
3109
        editor.ui.registry.addMenuButton('tablecellbackgroundcolor', {
3110
          icon: 'cell-background-color',
3111
          tooltip: 'Background color',
3112
          fetch: callback => callback(buildColorMenu(editor, getTableBackgroundColorMap(editor), 'background-color')),
3113
          onSetup: selectionTargets.onSetupCellOrRow
3114
        });
3115
        editor.ui.registry.addMenuButton('tablecellbordercolor', {
3116
          icon: 'cell-border-color',
3117
          tooltip: 'Border color',
3118
          fetch: callback => callback(buildColorMenu(editor, getTableBorderColorMap(editor), 'border-color')),
3119
          onSetup: selectionTargets.onSetupCellOrRow
3120
        });
3121
      }
3122
      addToggleButtonIfRegistered('tablecaption', {
3123
        tooltip: 'Table caption',
3124
        icon: 'table-caption',
3125
        command: 'mceTableToggleCaption',
3126
        onSetup: selectionTargets.onSetupTableWithCaption
3127
      });
3128
      addToggleButtonIfRegistered('tablerowheader', {
3129
        tooltip: 'Row header',
3130
        icon: 'table-top-header',
3131
        command: 'mceTableRowType',
3132
        onAction: changeRowHeader(editor),
3133
        onSetup: selectionTargets.onSetupTableRowHeaders
3134
      });
3135
      addToggleButtonIfRegistered('tablecolheader', {
3136
        tooltip: 'Column header',
3137
        icon: 'table-left-header',
3138
        command: 'mceTableColType',
3139
        onAction: changeColumnHeader(editor),
3140
        onSetup: selectionTargets.onSetupTableColumnHeaders
3141
      });
3142
    };
3143
    const addToolbars = editor => {
3144
      const isEditableTable = table => editor.dom.is(table, 'table') && editor.getBody().contains(table) && editor.dom.isEditable(table.parentNode);
3145
      const toolbar = getToolbar(editor);
3146
      if (toolbar.length > 0) {
3147
        editor.ui.registry.addContextToolbar('table', {
3148
          predicate: isEditableTable,
3149
          items: toolbar,
3150
          scope: 'node',
3151
          position: 'node'
3152
        });
3153
      }
3154
    };
3155
 
3156
    const onSetupEditable = editor => api => {
3157
      const nodeChanged = () => {
3158
        api.setEnabled(editor.selection.isEditable());
3159
      };
3160
      editor.on('NodeChange', nodeChanged);
3161
      nodeChanged();
3162
      return () => {
3163
        editor.off('NodeChange', nodeChanged);
3164
      };
3165
    };
3166
    const addMenuItems = (editor, selectionTargets) => {
3167
      const cmd = command => () => editor.execCommand(command);
3168
      const addMenuIfRegistered = (name, spec) => {
3169
        if (editor.queryCommandSupported(spec.command)) {
3170
          editor.ui.registry.addMenuItem(name, {
3171
            ...spec,
3172
            onAction: isFunction(spec.onAction) ? spec.onAction : cmd(spec.command)
3173
          });
3174
          return true;
3175
        } else {
3176
          return false;
3177
        }
3178
      };
3179
      const addToggleMenuIfRegistered = (name, spec) => {
3180
        if (editor.queryCommandSupported(spec.command)) {
3181
          editor.ui.registry.addToggleMenuItem(name, {
3182
            ...spec,
3183
            onAction: isFunction(spec.onAction) ? spec.onAction : cmd(spec.command)
3184
          });
3185
        }
3186
      };
3187
      const insertTableAction = data => {
3188
        editor.execCommand('mceInsertTable', false, {
3189
          rows: data.numRows,
3190
          columns: data.numColumns
3191
        });
3192
      };
3193
      const hasRowMenuItems = [
3194
        addMenuIfRegistered('tableinsertrowbefore', {
3195
          text: 'Insert row before',
3196
          icon: 'table-insert-row-above',
3197
          command: 'mceTableInsertRowBefore',
3198
          onSetup: selectionTargets.onSetupCellOrRow
3199
        }),
3200
        addMenuIfRegistered('tableinsertrowafter', {
3201
          text: 'Insert row after',
3202
          icon: 'table-insert-row-after',
3203
          command: 'mceTableInsertRowAfter',
3204
          onSetup: selectionTargets.onSetupCellOrRow
3205
        }),
3206
        addMenuIfRegistered('tabledeleterow', {
3207
          text: 'Delete row',
3208
          icon: 'table-delete-row',
3209
          command: 'mceTableDeleteRow',
3210
          onSetup: selectionTargets.onSetupCellOrRow
3211
        }),
3212
        addMenuIfRegistered('tablerowprops', {
3213
          text: 'Row properties',
3214
          icon: 'table-row-properties',
3215
          command: 'mceTableRowProps',
3216
          onSetup: selectionTargets.onSetupCellOrRow
3217
        }),
3218
        addMenuIfRegistered('tablecutrow', {
3219
          text: 'Cut row',
3220
          icon: 'cut-row',
3221
          command: 'mceTableCutRow',
3222
          onSetup: selectionTargets.onSetupCellOrRow
3223
        }),
3224
        addMenuIfRegistered('tablecopyrow', {
3225
          text: 'Copy row',
3226
          icon: 'duplicate-row',
3227
          command: 'mceTableCopyRow',
3228
          onSetup: selectionTargets.onSetupCellOrRow
3229
        }),
3230
        addMenuIfRegistered('tablepasterowbefore', {
3231
          text: 'Paste row before',
3232
          icon: 'paste-row-before',
3233
          command: 'mceTablePasteRowBefore',
3234
          onSetup: selectionTargets.onSetupPasteable(getRows)
3235
        }),
3236
        addMenuIfRegistered('tablepasterowafter', {
3237
          text: 'Paste row after',
3238
          icon: 'paste-row-after',
3239
          command: 'mceTablePasteRowAfter',
3240
          onSetup: selectionTargets.onSetupPasteable(getRows)
3241
        })
3242
      ];
3243
      const hasColumnMenuItems = [
3244
        addMenuIfRegistered('tableinsertcolumnbefore', {
3245
          text: 'Insert column before',
3246
          icon: 'table-insert-column-before',
3247
          command: 'mceTableInsertColBefore',
3248
          onSetup: selectionTargets.onSetupColumn('onFirst')
3249
        }),
3250
        addMenuIfRegistered('tableinsertcolumnafter', {
3251
          text: 'Insert column after',
3252
          icon: 'table-insert-column-after',
3253
          command: 'mceTableInsertColAfter',
3254
          onSetup: selectionTargets.onSetupColumn('onLast')
3255
        }),
3256
        addMenuIfRegistered('tabledeletecolumn', {
3257
          text: 'Delete column',
3258
          icon: 'table-delete-column',
3259
          command: 'mceTableDeleteCol',
3260
          onSetup: selectionTargets.onSetupColumn('onAny')
3261
        }),
3262
        addMenuIfRegistered('tablecutcolumn', {
3263
          text: 'Cut column',
3264
          icon: 'cut-column',
3265
          command: 'mceTableCutCol',
3266
          onSetup: selectionTargets.onSetupColumn('onAny')
3267
        }),
3268
        addMenuIfRegistered('tablecopycolumn', {
3269
          text: 'Copy column',
3270
          icon: 'duplicate-column',
3271
          command: 'mceTableCopyCol',
3272
          onSetup: selectionTargets.onSetupColumn('onAny')
3273
        }),
3274
        addMenuIfRegistered('tablepastecolumnbefore', {
3275
          text: 'Paste column before',
3276
          icon: 'paste-column-before',
3277
          command: 'mceTablePasteColBefore',
3278
          onSetup: selectionTargets.onSetupPasteableColumn(getColumns, 'onFirst')
3279
        }),
3280
        addMenuIfRegistered('tablepastecolumnafter', {
3281
          text: 'Paste column after',
3282
          icon: 'paste-column-after',
3283
          command: 'mceTablePasteColAfter',
3284
          onSetup: selectionTargets.onSetupPasteableColumn(getColumns, 'onLast')
3285
        })
3286
      ];
3287
      const hasCellMenuItems = [
3288
        addMenuIfRegistered('tablecellprops', {
3289
          text: 'Cell properties',
3290
          icon: 'table-cell-properties',
3291
          command: 'mceTableCellProps',
3292
          onSetup: selectionTargets.onSetupCellOrRow
3293
        }),
3294
        addMenuIfRegistered('tablemergecells', {
3295
          text: 'Merge cells',
3296
          icon: 'table-merge-cells',
3297
          command: 'mceTableMergeCells',
3298
          onSetup: selectionTargets.onSetupMergeable
3299
        }),
3300
        addMenuIfRegistered('tablesplitcells', {
3301
          text: 'Split cell',
3302
          icon: 'table-split-cells',
3303
          command: 'mceTableSplitCells',
3304
          onSetup: selectionTargets.onSetupUnmergeable
3305
        })
3306
      ];
3307
      if (!hasTableGrid(editor)) {
3308
        editor.ui.registry.addMenuItem('inserttable', {
3309
          text: 'Table',
3310
          icon: 'table',
3311
          onAction: cmd('mceInsertTableDialog'),
3312
          onSetup: onSetupEditable(editor)
3313
        });
3314
      } else {
3315
        editor.ui.registry.addNestedMenuItem('inserttable', {
3316
          text: 'Table',
3317
          icon: 'table',
3318
          getSubmenuItems: () => [{
3319
              type: 'fancymenuitem',
3320
              fancytype: 'inserttable',
3321
              onAction: insertTableAction
3322
            }],
3323
          onSetup: onSetupEditable(editor)
3324
        });
3325
      }
3326
      editor.ui.registry.addMenuItem('inserttabledialog', {
3327
        text: 'Insert table',
3328
        icon: 'table',
3329
        onAction: cmd('mceInsertTableDialog'),
3330
        onSetup: onSetupEditable(editor)
3331
      });
3332
      addMenuIfRegistered('tableprops', {
3333
        text: 'Table properties',
3334
        onSetup: selectionTargets.onSetupTable,
3335
        command: 'mceTableProps'
3336
      });
3337
      addMenuIfRegistered('deletetable', {
3338
        text: 'Delete table',
3339
        icon: 'table-delete-table',
3340
        onSetup: selectionTargets.onSetupTable,
3341
        command: 'mceTableDelete'
3342
      });
3343
      if (contains(hasRowMenuItems, true)) {
3344
        editor.ui.registry.addNestedMenuItem('row', {
3345
          type: 'nestedmenuitem',
3346
          text: 'Row',
3347
          getSubmenuItems: constant('tableinsertrowbefore tableinsertrowafter tabledeleterow tablerowprops | tablecutrow tablecopyrow tablepasterowbefore tablepasterowafter')
3348
        });
3349
      }
3350
      if (contains(hasColumnMenuItems, true)) {
3351
        editor.ui.registry.addNestedMenuItem('column', {
3352
          type: 'nestedmenuitem',
3353
          text: 'Column',
3354
          getSubmenuItems: constant('tableinsertcolumnbefore tableinsertcolumnafter tabledeletecolumn | tablecutcolumn tablecopycolumn tablepastecolumnbefore tablepastecolumnafter')
3355
        });
3356
      }
3357
      if (contains(hasCellMenuItems, true)) {
3358
        editor.ui.registry.addNestedMenuItem('cell', {
3359
          type: 'nestedmenuitem',
3360
          text: 'Cell',
3361
          getSubmenuItems: constant('tablecellprops tablemergecells tablesplitcells')
3362
        });
3363
      }
3364
      editor.ui.registry.addContextMenu('table', {
3365
        update: () => {
3366
          selectionTargets.resetTargets();
3367
          return selectionTargets.targets().fold(constant(''), targets => {
3368
            if (name(targets.element) === 'caption') {
3369
              return 'tableprops deletetable';
3370
            } else {
3371
              return 'cell row column | advtablesort | tableprops deletetable';
3372
            }
3373
          });
3374
        }
3375
      });
3376
      const tableClassList = filterNoneItem(getTableClassList(editor));
3377
      if (tableClassList.length !== 0 && editor.queryCommandSupported('mceTableToggleClass')) {
3378
        editor.ui.registry.addNestedMenuItem('tableclass', {
3379
          icon: 'table-classes',
3380
          text: 'Table styles',
3381
          getSubmenuItems: () => buildMenuItems(editor, tableClassList, 'tableclass', value => editor.execCommand('mceTableToggleClass', false, value)),
3382
          onSetup: selectionTargets.onSetupTable
3383
        });
3384
      }
3385
      const tableCellClassList = filterNoneItem(getCellClassList(editor));
3386
      if (tableCellClassList.length !== 0 && editor.queryCommandSupported('mceTableCellToggleClass')) {
3387
        editor.ui.registry.addNestedMenuItem('tablecellclass', {
3388
          icon: 'table-cell-classes',
3389
          text: 'Cell styles',
3390
          getSubmenuItems: () => buildMenuItems(editor, tableCellClassList, 'tablecellclass', value => editor.execCommand('mceTableCellToggleClass', false, value)),
3391
          onSetup: selectionTargets.onSetupCellOrRow
3392
        });
3393
      }
3394
      if (editor.queryCommandSupported('mceTableApplyCellStyle')) {
3395
        editor.ui.registry.addNestedMenuItem('tablecellvalign', {
3396
          icon: 'vertical-align',
3397
          text: 'Vertical align',
3398
          getSubmenuItems: () => buildMenuItems(editor, verticalAlignValues, 'tablecellverticalalign', applyTableCellStyle(editor, 'vertical-align')),
3399
          onSetup: selectionTargets.onSetupCellOrRow
3400
        });
3401
        editor.ui.registry.addNestedMenuItem('tablecellborderwidth', {
3402
          icon: 'border-width',
3403
          text: 'Border width',
3404
          getSubmenuItems: () => buildMenuItems(editor, getTableBorderWidths(editor), 'tablecellborderwidth', applyTableCellStyle(editor, 'border-width')),
3405
          onSetup: selectionTargets.onSetupCellOrRow
3406
        });
3407
        editor.ui.registry.addNestedMenuItem('tablecellborderstyle', {
3408
          icon: 'border-style',
3409
          text: 'Border style',
3410
          getSubmenuItems: () => buildMenuItems(editor, getTableBorderStyles(editor), 'tablecellborderstyle', applyTableCellStyle(editor, 'border-style')),
3411
          onSetup: selectionTargets.onSetupCellOrRow
3412
        });
3413
        editor.ui.registry.addNestedMenuItem('tablecellbackgroundcolor', {
3414
          icon: 'cell-background-color',
3415
          text: 'Background color',
3416
          getSubmenuItems: () => buildColorMenu(editor, getTableBackgroundColorMap(editor), 'background-color'),
3417
          onSetup: selectionTargets.onSetupCellOrRow
3418
        });
3419
        editor.ui.registry.addNestedMenuItem('tablecellbordercolor', {
3420
          icon: 'cell-border-color',
3421
          text: 'Border color',
3422
          getSubmenuItems: () => buildColorMenu(editor, getTableBorderColorMap(editor), 'border-color'),
3423
          onSetup: selectionTargets.onSetupCellOrRow
3424
        });
3425
      }
3426
      addToggleMenuIfRegistered('tablecaption', {
3427
        icon: 'table-caption',
3428
        text: 'Table caption',
3429
        command: 'mceTableToggleCaption',
3430
        onSetup: selectionTargets.onSetupTableWithCaption
3431
      });
3432
      addToggleMenuIfRegistered('tablerowheader', {
3433
        text: 'Row header',
3434
        icon: 'table-top-header',
3435
        command: 'mceTableRowType',
3436
        onAction: changeRowHeader(editor),
3437
        onSetup: selectionTargets.onSetupTableRowHeaders
3438
      });
3439
      addToggleMenuIfRegistered('tablecolheader', {
3440
        text: 'Column header',
3441
        icon: 'table-left-header',
3442
        command: 'mceTableColType',
3443
        onAction: changeColumnHeader(editor),
3444
        onSetup: selectionTargets.onSetupTableRowHeaders
3445
      });
3446
    };
3447
 
3448
    const Plugin = editor => {
3449
      const selectionTargets = getSelectionTargets(editor);
3450
      register(editor);
3451
      registerCommands(editor);
3452
      addMenuItems(editor, selectionTargets);
3453
      addButtons(editor, selectionTargets);
3454
      addToolbars(editor);
3455
    };
3456
    var Plugin$1 = () => {
3457
      global$3.add('table', Plugin);
3458
    };
3459
 
3460
    Plugin$1();
3461
 
3462
})();