Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/**
2
 * TinyMCE version 6.8.3 (2024-02-08)
3
 */
4
 
5
(function () {
6
    'use strict';
7
 
8
    var global$4 = tinymce.util.Tools.resolve('tinymce.PluginManager');
9
 
10
    const getPrototypeOf = Object.getPrototypeOf;
11
    const hasProto = (v, constructor, predicate) => {
12
      var _a;
13
      if (predicate(v, constructor.prototype)) {
14
        return true;
15
      } else {
16
        return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
17
      }
18
    };
19
    const typeOf = x => {
20
      const t = typeof x;
21
      if (x === null) {
22
        return 'null';
23
      } else if (t === 'object' && Array.isArray(x)) {
24
        return 'array';
25
      } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
26
        return 'string';
27
      } else {
28
        return t;
29
      }
30
    };
31
    const isType = type => value => typeOf(value) === type;
32
    const isSimpleType = type => value => typeof value === type;
33
    const eq = t => a => t === a;
34
    const is = (value, constructor) => isObject(value) && hasProto(value, constructor, (o, proto) => getPrototypeOf(o) === proto);
35
    const isString = isType('string');
36
    const isObject = isType('object');
37
    const isPlainObject = value => is(value, Object);
38
    const isArray = isType('array');
39
    const isNull = eq(null);
40
    const isBoolean = isSimpleType('boolean');
41
    const isNullable = a => a === null || a === undefined;
42
    const isNonNullable = a => !isNullable(a);
43
    const isFunction = isSimpleType('function');
44
    const isNumber = isSimpleType('number');
45
    const isArrayOf = (value, pred) => {
46
      if (isArray(value)) {
47
        for (let i = 0, len = value.length; i < len; ++i) {
48
          if (!pred(value[i])) {
49
            return false;
50
          }
51
        }
52
        return true;
53
      }
54
      return false;
55
    };
56
 
57
    const noop = () => {
58
    };
59
 
60
    class Optional {
61
      constructor(tag, value) {
62
        this.tag = tag;
63
        this.value = value;
64
      }
65
      static some(value) {
66
        return new Optional(true, value);
67
      }
68
      static none() {
69
        return Optional.singletonNone;
70
      }
71
      fold(onNone, onSome) {
72
        if (this.tag) {
73
          return onSome(this.value);
74
        } else {
75
          return onNone();
76
        }
77
      }
78
      isSome() {
79
        return this.tag;
80
      }
81
      isNone() {
82
        return !this.tag;
83
      }
84
      map(mapper) {
85
        if (this.tag) {
86
          return Optional.some(mapper(this.value));
87
        } else {
88
          return Optional.none();
89
        }
90
      }
91
      bind(binder) {
92
        if (this.tag) {
93
          return binder(this.value);
94
        } else {
95
          return Optional.none();
96
        }
97
      }
98
      exists(predicate) {
99
        return this.tag && predicate(this.value);
100
      }
101
      forall(predicate) {
102
        return !this.tag || predicate(this.value);
103
      }
104
      filter(predicate) {
105
        if (!this.tag || predicate(this.value)) {
106
          return this;
107
        } else {
108
          return Optional.none();
109
        }
110
      }
111
      getOr(replacement) {
112
        return this.tag ? this.value : replacement;
113
      }
114
      or(replacement) {
115
        return this.tag ? this : replacement;
116
      }
117
      getOrThunk(thunk) {
118
        return this.tag ? this.value : thunk();
119
      }
120
      orThunk(thunk) {
121
        return this.tag ? this : thunk();
122
      }
123
      getOrDie(message) {
124
        if (!this.tag) {
125
          throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
126
        } else {
127
          return this.value;
128
        }
129
      }
130
      static from(value) {
131
        return isNonNullable(value) ? Optional.some(value) : Optional.none();
132
      }
133
      getOrNull() {
134
        return this.tag ? this.value : null;
135
      }
136
      getOrUndefined() {
137
        return this.value;
138
      }
139
      each(worker) {
140
        if (this.tag) {
141
          worker(this.value);
142
        }
143
      }
144
      toArray() {
145
        return this.tag ? [this.value] : [];
146
      }
147
      toString() {
148
        return this.tag ? `some(${ this.value })` : 'none()';
149
      }
150
    }
151
    Optional.singletonNone = new Optional(false);
152
 
153
    const keys = Object.keys;
154
    const hasOwnProperty = Object.hasOwnProperty;
155
    const each = (obj, f) => {
156
      const props = keys(obj);
157
      for (let k = 0, len = props.length; k < len; k++) {
158
        const i = props[k];
159
        const x = obj[i];
160
        f(x, i);
161
      }
162
    };
163
    const objAcc = r => (x, i) => {
164
      r[i] = x;
165
    };
166
    const internalFilter = (obj, pred, onTrue, onFalse) => {
167
      each(obj, (x, i) => {
168
        (pred(x, i) ? onTrue : onFalse)(x, i);
169
      });
170
    };
171
    const filter = (obj, pred) => {
172
      const t = {};
173
      internalFilter(obj, pred, objAcc(t), noop);
174
      return t;
175
    };
176
    const has = (obj, key) => hasOwnProperty.call(obj, key);
177
    const hasNonNullableKey = (obj, key) => has(obj, key) && obj[key] !== undefined && obj[key] !== null;
178
 
179
    const nativePush = Array.prototype.push;
180
    const flatten = xs => {
181
      const r = [];
182
      for (let i = 0, len = xs.length; i < len; ++i) {
183
        if (!isArray(xs[i])) {
184
          throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
185
        }
186
        nativePush.apply(r, xs[i]);
187
      }
188
      return r;
189
    };
190
    const get = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
191
    const head = xs => get(xs, 0);
192
    const findMap = (arr, f) => {
193
      for (let i = 0; i < arr.length; i++) {
194
        const r = f(arr[i], i);
195
        if (r.isSome()) {
196
          return r;
197
        }
198
      }
199
      return Optional.none();
200
    };
201
 
202
    typeof window !== 'undefined' ? window : Function('return this;')();
203
 
204
    const rawSet = (dom, key, value) => {
205
      if (isString(value) || isBoolean(value) || isNumber(value)) {
206
        dom.setAttribute(key, value + '');
207
      } else {
208
        console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
209
        throw new Error('Attribute value was not simple');
210
      }
211
    };
212
    const set = (element, key, value) => {
213
      rawSet(element.dom, key, value);
214
    };
215
    const remove = (element, key) => {
216
      element.dom.removeAttribute(key);
217
    };
218
 
219
    const fromHtml = (html, scope) => {
220
      const doc = scope || document;
221
      const div = doc.createElement('div');
222
      div.innerHTML = html;
223
      if (!div.hasChildNodes() || div.childNodes.length > 1) {
224
        const message = 'HTML does not have a single root node';
225
        console.error(message, html);
226
        throw new Error(message);
227
      }
228
      return fromDom(div.childNodes[0]);
229
    };
230
    const fromTag = (tag, scope) => {
231
      const doc = scope || document;
232
      const node = doc.createElement(tag);
233
      return fromDom(node);
234
    };
235
    const fromText = (text, scope) => {
236
      const doc = scope || document;
237
      const node = doc.createTextNode(text);
238
      return fromDom(node);
239
    };
240
    const fromDom = node => {
241
      if (node === null || node === undefined) {
242
        throw new Error('Node cannot be null or undefined');
243
      }
244
      return { dom: node };
245
    };
246
    const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom);
247
    const SugarElement = {
248
      fromHtml,
249
      fromTag,
250
      fromText,
251
      fromDom,
252
      fromPoint
253
    };
254
 
255
    var global$3 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
256
 
257
    var global$2 = tinymce.util.Tools.resolve('tinymce.util.URI');
258
 
259
    const isNotEmpty = s => s.length > 0;
260
 
261
    const option = name => editor => editor.options.get(name);
262
    const register$2 = editor => {
263
      const registerOption = editor.options.register;
264
      registerOption('image_dimensions', {
265
        processor: 'boolean',
266
        default: true
267
      });
268
      registerOption('image_advtab', {
269
        processor: 'boolean',
270
        default: false
271
      });
272
      registerOption('image_uploadtab', {
273
        processor: 'boolean',
274
        default: true
275
      });
276
      registerOption('image_prepend_url', {
277
        processor: 'string',
278
        default: ''
279
      });
280
      registerOption('image_class_list', { processor: 'object[]' });
281
      registerOption('image_description', {
282
        processor: 'boolean',
283
        default: true
284
      });
285
      registerOption('image_title', {
286
        processor: 'boolean',
287
        default: false
288
      });
289
      registerOption('image_caption', {
290
        processor: 'boolean',
291
        default: false
292
      });
293
      registerOption('image_list', {
294
        processor: value => {
295
          const valid = value === false || isString(value) || isArrayOf(value, isObject) || isFunction(value);
296
          return valid ? {
297
            value,
298
            valid
299
          } : {
300
            valid: false,
301
            message: 'Must be false, a string, an array or a function.'
302
          };
303
        },
304
        default: false
305
      });
306
    };
307
    const hasDimensions = option('image_dimensions');
308
    const hasAdvTab = option('image_advtab');
309
    const hasUploadTab = option('image_uploadtab');
310
    const getPrependUrl = option('image_prepend_url');
311
    const getClassList = option('image_class_list');
312
    const hasDescription = option('image_description');
313
    const hasImageTitle = option('image_title');
314
    const hasImageCaption = option('image_caption');
315
    const getImageList = option('image_list');
316
    const showAccessibilityOptions = option('a11y_advanced_options');
317
    const isAutomaticUploadsEnabled = option('automatic_uploads');
318
    const hasUploadUrl = editor => isNotEmpty(editor.options.get('images_upload_url'));
319
    const hasUploadHandler = editor => isNonNullable(editor.options.get('images_upload_handler'));
320
 
321
    const parseIntAndGetMax = (val1, val2) => Math.max(parseInt(val1, 10), parseInt(val2, 10));
322
    const getImageSize = url => new Promise(callback => {
323
      const img = document.createElement('img');
324
      const done = dimensions => {
325
        img.onload = img.onerror = null;
326
        if (img.parentNode) {
327
          img.parentNode.removeChild(img);
328
        }
329
        callback(dimensions);
330
      };
331
      img.onload = () => {
332
        const width = parseIntAndGetMax(img.width, img.clientWidth);
333
        const height = parseIntAndGetMax(img.height, img.clientHeight);
334
        const dimensions = {
335
          width,
336
          height
337
        };
338
        done(Promise.resolve(dimensions));
339
      };
340
      img.onerror = () => {
341
        done(Promise.reject(`Failed to get image dimensions for: ${ url }`));
342
      };
343
      const style = img.style;
344
      style.visibility = 'hidden';
345
      style.position = 'fixed';
346
      style.bottom = style.left = '0px';
347
      style.width = style.height = 'auto';
348
      document.body.appendChild(img);
349
      img.src = url;
350
    });
351
    const removePixelSuffix = value => {
352
      if (value) {
353
        value = value.replace(/px$/, '');
354
      }
355
      return value;
356
    };
357
    const addPixelSuffix = value => {
358
      if (value.length > 0 && /^[0-9]+$/.test(value)) {
359
        value += 'px';
360
      }
361
      return value;
362
    };
363
    const mergeMargins = css => {
364
      if (css.margin) {
365
        const splitMargin = String(css.margin).split(' ');
366
        switch (splitMargin.length) {
367
        case 1:
368
          css['margin-top'] = css['margin-top'] || splitMargin[0];
369
          css['margin-right'] = css['margin-right'] || splitMargin[0];
370
          css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
371
          css['margin-left'] = css['margin-left'] || splitMargin[0];
372
          break;
373
        case 2:
374
          css['margin-top'] = css['margin-top'] || splitMargin[0];
375
          css['margin-right'] = css['margin-right'] || splitMargin[1];
376
          css['margin-bottom'] = css['margin-bottom'] || splitMargin[0];
377
          css['margin-left'] = css['margin-left'] || splitMargin[1];
378
          break;
379
        case 3:
380
          css['margin-top'] = css['margin-top'] || splitMargin[0];
381
          css['margin-right'] = css['margin-right'] || splitMargin[1];
382
          css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
383
          css['margin-left'] = css['margin-left'] || splitMargin[1];
384
          break;
385
        case 4:
386
          css['margin-top'] = css['margin-top'] || splitMargin[0];
387
          css['margin-right'] = css['margin-right'] || splitMargin[1];
388
          css['margin-bottom'] = css['margin-bottom'] || splitMargin[2];
389
          css['margin-left'] = css['margin-left'] || splitMargin[3];
390
        }
391
        delete css.margin;
392
      }
393
      return css;
394
    };
395
    const createImageList = (editor, callback) => {
396
      const imageList = getImageList(editor);
397
      if (isString(imageList)) {
398
        fetch(imageList).then(res => {
399
          if (res.ok) {
400
            res.json().then(callback);
401
          }
402
        });
403
      } else if (isFunction(imageList)) {
404
        imageList(callback);
405
      } else {
406
        callback(imageList);
407
      }
408
    };
409
    const waitLoadImage = (editor, data, imgElm) => {
410
      const selectImage = () => {
411
        imgElm.onload = imgElm.onerror = null;
412
        if (editor.selection) {
413
          editor.selection.select(imgElm);
414
          editor.nodeChanged();
415
        }
416
      };
417
      imgElm.onload = () => {
418
        if (!data.width && !data.height && hasDimensions(editor)) {
419
          editor.dom.setAttribs(imgElm, {
420
            width: String(imgElm.clientWidth),
421
            height: String(imgElm.clientHeight)
422
          });
423
        }
424
        selectImage();
425
      };
426
      imgElm.onerror = selectImage;
427
    };
428
    const blobToDataUri = blob => new Promise((resolve, reject) => {
429
      const reader = new FileReader();
430
      reader.onload = () => {
431
        resolve(reader.result);
432
      };
433
      reader.onerror = () => {
434
        var _a;
435
        reject((_a = reader.error) === null || _a === void 0 ? void 0 : _a.message);
436
      };
437
      reader.readAsDataURL(blob);
438
    });
439
    const isPlaceholderImage = imgElm => imgElm.nodeName === 'IMG' && (imgElm.hasAttribute('data-mce-object') || imgElm.hasAttribute('data-mce-placeholder'));
440
    const isSafeImageUrl = (editor, src) => {
441
      const getOption = editor.options.get;
442
      return global$2.isDomSafe(src, 'img', {
443
        allow_html_data_urls: getOption('allow_html_data_urls'),
444
        allow_script_urls: getOption('allow_script_urls'),
445
        allow_svg_data_urls: getOption('allow_svg_data_urls')
446
      });
447
    };
448
 
449
    const DOM = global$3.DOM;
450
    const getHspace = image => {
451
      if (image.style.marginLeft && image.style.marginRight && image.style.marginLeft === image.style.marginRight) {
452
        return removePixelSuffix(image.style.marginLeft);
453
      } else {
454
        return '';
455
      }
456
    };
457
    const getVspace = image => {
458
      if (image.style.marginTop && image.style.marginBottom && image.style.marginTop === image.style.marginBottom) {
459
        return removePixelSuffix(image.style.marginTop);
460
      } else {
461
        return '';
462
      }
463
    };
464
    const getBorder = image => {
465
      if (image.style.borderWidth) {
466
        return removePixelSuffix(image.style.borderWidth);
467
      } else {
468
        return '';
469
      }
470
    };
471
    const getAttrib = (image, name) => {
472
      var _a;
473
      if (image.hasAttribute(name)) {
474
        return (_a = image.getAttribute(name)) !== null && _a !== void 0 ? _a : '';
475
      } else {
476
        return '';
477
      }
478
    };
479
    const hasCaption = image => image.parentNode !== null && image.parentNode.nodeName === 'FIGURE';
480
    const updateAttrib = (image, name, value) => {
481
      if (value === '' || value === null) {
482
        image.removeAttribute(name);
483
      } else {
484
        image.setAttribute(name, value);
485
      }
486
    };
487
    const wrapInFigure = image => {
488
      const figureElm = DOM.create('figure', { class: 'image' });
489
      DOM.insertAfter(figureElm, image);
490
      figureElm.appendChild(image);
491
      figureElm.appendChild(DOM.create('figcaption', { contentEditable: 'true' }, 'Caption'));
492
      figureElm.contentEditable = 'false';
493
    };
494
    const removeFigure = image => {
495
      const figureElm = image.parentNode;
496
      if (isNonNullable(figureElm)) {
497
        DOM.insertAfter(image, figureElm);
498
        DOM.remove(figureElm);
499
      }
500
    };
501
    const toggleCaption = image => {
502
      if (hasCaption(image)) {
503
        removeFigure(image);
504
      } else {
505
        wrapInFigure(image);
506
      }
507
    };
508
    const normalizeStyle = (image, normalizeCss) => {
509
      const attrValue = image.getAttribute('style');
510
      const value = normalizeCss(attrValue !== null ? attrValue : '');
511
      if (value.length > 0) {
512
        image.setAttribute('style', value);
513
        image.setAttribute('data-mce-style', value);
514
      } else {
515
        image.removeAttribute('style');
516
      }
517
    };
518
    const setSize = (name, normalizeCss) => (image, name, value) => {
519
      const styles = image.style;
520
      if (styles[name]) {
521
        styles[name] = addPixelSuffix(value);
522
        normalizeStyle(image, normalizeCss);
523
      } else {
524
        updateAttrib(image, name, value);
525
      }
526
    };
527
    const getSize = (image, name) => {
528
      if (image.style[name]) {
529
        return removePixelSuffix(image.style[name]);
530
      } else {
531
        return getAttrib(image, name);
532
      }
533
    };
534
    const setHspace = (image, value) => {
535
      const pxValue = addPixelSuffix(value);
536
      image.style.marginLeft = pxValue;
537
      image.style.marginRight = pxValue;
538
    };
539
    const setVspace = (image, value) => {
540
      const pxValue = addPixelSuffix(value);
541
      image.style.marginTop = pxValue;
542
      image.style.marginBottom = pxValue;
543
    };
544
    const setBorder = (image, value) => {
545
      const pxValue = addPixelSuffix(value);
546
      image.style.borderWidth = pxValue;
547
    };
548
    const setBorderStyle = (image, value) => {
549
      image.style.borderStyle = value;
550
    };
551
    const getBorderStyle = image => {
552
      var _a;
553
      return (_a = image.style.borderStyle) !== null && _a !== void 0 ? _a : '';
554
    };
555
    const isFigure = elm => isNonNullable(elm) && elm.nodeName === 'FIGURE';
556
    const isImage = elm => elm.nodeName === 'IMG';
557
    const getIsDecorative = image => DOM.getAttrib(image, 'alt').length === 0 && DOM.getAttrib(image, 'role') === 'presentation';
558
    const getAlt = image => {
559
      if (getIsDecorative(image)) {
560
        return '';
561
      } else {
562
        return getAttrib(image, 'alt');
563
      }
564
    };
565
    const defaultData = () => ({
566
      src: '',
567
      alt: '',
568
      title: '',
569
      width: '',
570
      height: '',
571
      class: '',
572
      style: '',
573
      caption: false,
574
      hspace: '',
575
      vspace: '',
576
      border: '',
577
      borderStyle: '',
578
      isDecorative: false
579
    });
580
    const getStyleValue = (normalizeCss, data) => {
581
      var _a;
582
      const image = document.createElement('img');
583
      updateAttrib(image, 'style', data.style);
584
      if (getHspace(image) || data.hspace !== '') {
585
        setHspace(image, data.hspace);
586
      }
587
      if (getVspace(image) || data.vspace !== '') {
588
        setVspace(image, data.vspace);
589
      }
590
      if (getBorder(image) || data.border !== '') {
591
        setBorder(image, data.border);
592
      }
593
      if (getBorderStyle(image) || data.borderStyle !== '') {
594
        setBorderStyle(image, data.borderStyle);
595
      }
596
      return normalizeCss((_a = image.getAttribute('style')) !== null && _a !== void 0 ? _a : '');
597
    };
598
    const create = (normalizeCss, data) => {
599
      const image = document.createElement('img');
600
      write(normalizeCss, {
601
        ...data,
602
        caption: false
603
      }, image);
604
      setAlt(image, data.alt, data.isDecorative);
605
      if (data.caption) {
606
        const figure = DOM.create('figure', { class: 'image' });
607
        figure.appendChild(image);
608
        figure.appendChild(DOM.create('figcaption', { contentEditable: 'true' }, 'Caption'));
609
        figure.contentEditable = 'false';
610
        return figure;
611
      } else {
612
        return image;
613
      }
614
    };
615
    const read = (normalizeCss, image) => ({
616
      src: getAttrib(image, 'src'),
617
      alt: getAlt(image),
618
      title: getAttrib(image, 'title'),
619
      width: getSize(image, 'width'),
620
      height: getSize(image, 'height'),
621
      class: getAttrib(image, 'class'),
622
      style: normalizeCss(getAttrib(image, 'style')),
623
      caption: hasCaption(image),
624
      hspace: getHspace(image),
625
      vspace: getVspace(image),
626
      border: getBorder(image),
627
      borderStyle: getBorderStyle(image),
628
      isDecorative: getIsDecorative(image)
629
    });
630
    const updateProp = (image, oldData, newData, name, set) => {
631
      if (newData[name] !== oldData[name]) {
632
        set(image, name, String(newData[name]));
633
      }
634
    };
635
    const setAlt = (image, alt, isDecorative) => {
636
      if (isDecorative) {
637
        DOM.setAttrib(image, 'role', 'presentation');
638
        const sugarImage = SugarElement.fromDom(image);
639
        set(sugarImage, 'alt', '');
640
      } else {
641
        if (isNull(alt)) {
642
          const sugarImage = SugarElement.fromDom(image);
643
          remove(sugarImage, 'alt');
644
        } else {
645
          const sugarImage = SugarElement.fromDom(image);
646
          set(sugarImage, 'alt', alt);
647
        }
648
        if (DOM.getAttrib(image, 'role') === 'presentation') {
649
          DOM.setAttrib(image, 'role', '');
650
        }
651
      }
652
    };
653
    const updateAlt = (image, oldData, newData) => {
654
      if (newData.alt !== oldData.alt || newData.isDecorative !== oldData.isDecorative) {
655
        setAlt(image, newData.alt, newData.isDecorative);
656
      }
657
    };
658
    const normalized = (set, normalizeCss) => (image, name, value) => {
659
      set(image, value);
660
      normalizeStyle(image, normalizeCss);
661
    };
662
    const write = (normalizeCss, newData, image) => {
663
      const oldData = read(normalizeCss, image);
664
      updateProp(image, oldData, newData, 'caption', (image, _name, _value) => toggleCaption(image));
665
      updateProp(image, oldData, newData, 'src', updateAttrib);
666
      updateProp(image, oldData, newData, 'title', updateAttrib);
667
      updateProp(image, oldData, newData, 'width', setSize('width', normalizeCss));
668
      updateProp(image, oldData, newData, 'height', setSize('height', normalizeCss));
669
      updateProp(image, oldData, newData, 'class', updateAttrib);
670
      updateProp(image, oldData, newData, 'style', normalized((image, value) => updateAttrib(image, 'style', value), normalizeCss));
671
      updateProp(image, oldData, newData, 'hspace', normalized(setHspace, normalizeCss));
672
      updateProp(image, oldData, newData, 'vspace', normalized(setVspace, normalizeCss));
673
      updateProp(image, oldData, newData, 'border', normalized(setBorder, normalizeCss));
674
      updateProp(image, oldData, newData, 'borderStyle', normalized(setBorderStyle, normalizeCss));
675
      updateAlt(image, oldData, newData);
676
    };
677
 
678
    const normalizeCss$1 = (editor, cssText) => {
679
      const css = editor.dom.styles.parse(cssText);
680
      const mergedCss = mergeMargins(css);
681
      const compressed = editor.dom.styles.parse(editor.dom.styles.serialize(mergedCss));
682
      return editor.dom.styles.serialize(compressed);
683
    };
684
    const getSelectedImage = editor => {
685
      const imgElm = editor.selection.getNode();
686
      const figureElm = editor.dom.getParent(imgElm, 'figure.image');
687
      if (figureElm) {
688
        return editor.dom.select('img', figureElm)[0];
689
      }
690
      if (imgElm && (imgElm.nodeName !== 'IMG' || isPlaceholderImage(imgElm))) {
691
        return null;
692
      }
693
      return imgElm;
694
    };
695
    const splitTextBlock = (editor, figure) => {
696
      var _a;
697
      const dom = editor.dom;
698
      const textBlockElements = filter(editor.schema.getTextBlockElements(), (_, parentElm) => !editor.schema.isValidChild(parentElm, 'figure'));
699
      const textBlock = dom.getParent(figure.parentNode, node => hasNonNullableKey(textBlockElements, node.nodeName), editor.getBody());
700
      if (textBlock) {
701
        return (_a = dom.split(textBlock, figure)) !== null && _a !== void 0 ? _a : figure;
702
      } else {
703
        return figure;
704
      }
705
    };
706
    const readImageDataFromSelection = editor => {
707
      const image = getSelectedImage(editor);
708
      return image ? read(css => normalizeCss$1(editor, css), image) : defaultData();
709
    };
710
    const insertImageAtCaret = (editor, data) => {
711
      const elm = create(css => normalizeCss$1(editor, css), data);
712
      editor.dom.setAttrib(elm, 'data-mce-id', '__mcenew');
713
      editor.focus();
714
      editor.selection.setContent(elm.outerHTML);
715
      const insertedElm = editor.dom.select('*[data-mce-id="__mcenew"]')[0];
716
      editor.dom.setAttrib(insertedElm, 'data-mce-id', null);
717
      if (isFigure(insertedElm)) {
718
        const figure = splitTextBlock(editor, insertedElm);
719
        editor.selection.select(figure);
720
      } else {
721
        editor.selection.select(insertedElm);
722
      }
723
    };
724
    const syncSrcAttr = (editor, image) => {
725
      editor.dom.setAttrib(image, 'src', image.getAttribute('src'));
726
    };
727
    const deleteImage = (editor, image) => {
728
      if (image) {
729
        const elm = editor.dom.is(image.parentNode, 'figure.image') ? image.parentNode : image;
730
        editor.dom.remove(elm);
731
        editor.focus();
732
        editor.nodeChanged();
733
        if (editor.dom.isEmpty(editor.getBody())) {
734
          editor.setContent('');
735
          editor.selection.setCursorLocation();
736
        }
737
      }
738
    };
739
    const writeImageDataToSelection = (editor, data) => {
740
      const image = getSelectedImage(editor);
741
      if (image) {
742
        write(css => normalizeCss$1(editor, css), data, image);
743
        syncSrcAttr(editor, image);
744
        if (isFigure(image.parentNode)) {
745
          const figure = image.parentNode;
746
          splitTextBlock(editor, figure);
747
          editor.selection.select(image.parentNode);
748
        } else {
749
          editor.selection.select(image);
750
          waitLoadImage(editor, data, image);
751
        }
752
      }
753
    };
754
    const sanitizeImageData = (editor, data) => {
755
      const src = data.src;
756
      return {
757
        ...data,
758
        src: isSafeImageUrl(editor, src) ? src : ''
759
      };
760
    };
761
    const insertOrUpdateImage = (editor, partialData) => {
762
      const image = getSelectedImage(editor);
763
      if (image) {
764
        const selectedImageData = read(css => normalizeCss$1(editor, css), image);
765
        const data = {
766
          ...selectedImageData,
767
          ...partialData
768
        };
769
        const sanitizedData = sanitizeImageData(editor, data);
770
        if (data.src) {
771
          writeImageDataToSelection(editor, sanitizedData);
772
        } else {
773
          deleteImage(editor, image);
774
        }
775
      } else if (partialData.src) {
776
        insertImageAtCaret(editor, {
777
          ...defaultData(),
778
          ...partialData
779
        });
780
      }
781
    };
782
 
783
    const deep = (old, nu) => {
784
      const bothObjects = isPlainObject(old) && isPlainObject(nu);
785
      return bothObjects ? deepMerge(old, nu) : nu;
786
    };
787
    const baseMerge = merger => {
788
      return (...objects) => {
789
        if (objects.length === 0) {
790
          throw new Error(`Can't merge zero objects`);
791
        }
792
        const ret = {};
793
        for (let j = 0; j < objects.length; j++) {
794
          const curObject = objects[j];
795
          for (const key in curObject) {
796
            if (has(curObject, key)) {
797
              ret[key] = merger(ret[key], curObject[key]);
798
            }
799
          }
800
        }
801
        return ret;
802
      };
803
    };
804
    const deepMerge = baseMerge(deep);
805
 
806
    var global$1 = tinymce.util.Tools.resolve('tinymce.util.ImageUploader');
807
 
808
    var global = tinymce.util.Tools.resolve('tinymce.util.Tools');
809
 
810
    const getValue = item => isString(item.value) ? item.value : '';
811
    const getText = item => {
812
      if (isString(item.text)) {
813
        return item.text;
814
      } else if (isString(item.title)) {
815
        return item.title;
816
      } else {
817
        return '';
818
      }
819
    };
820
    const sanitizeList = (list, extractValue) => {
821
      const out = [];
822
      global.each(list, item => {
823
        const text = getText(item);
824
        if (item.menu !== undefined) {
825
          const items = sanitizeList(item.menu, extractValue);
826
          out.push({
827
            text,
828
            items
829
          });
830
        } else {
831
          const value = extractValue(item);
832
          out.push({
833
            text,
834
            value
835
          });
836
        }
837
      });
838
      return out;
839
    };
840
    const sanitizer = (extractor = getValue) => list => {
841
      if (list) {
842
        return Optional.from(list).map(list => sanitizeList(list, extractor));
843
      } else {
844
        return Optional.none();
845
      }
846
    };
847
    const sanitize = list => sanitizer(getValue)(list);
848
    const isGroup = item => has(item, 'items');
849
    const findEntryDelegate = (list, value) => findMap(list, item => {
850
      if (isGroup(item)) {
851
        return findEntryDelegate(item.items, value);
852
      } else if (item.value === value) {
853
        return Optional.some(item);
854
      } else {
855
        return Optional.none();
856
      }
857
    });
858
    const findEntry = (optList, value) => optList.bind(list => findEntryDelegate(list, value));
859
    const ListUtils = {
860
      sanitizer,
861
      sanitize,
862
      findEntry
863
    };
864
 
865
    const makeTab$2 = _info => ({
866
      title: 'Advanced',
867
      name: 'advanced',
868
      items: [{
869
          type: 'grid',
870
          columns: 2,
871
          items: [
872
            {
873
              type: 'input',
874
              label: 'Vertical space',
875
              name: 'vspace',
876
              inputMode: 'numeric'
877
            },
878
            {
879
              type: 'input',
880
              label: 'Horizontal space',
881
              name: 'hspace',
882
              inputMode: 'numeric'
883
            },
884
            {
885
              type: 'input',
886
              label: 'Border width',
887
              name: 'border',
888
              inputMode: 'numeric'
889
            },
890
            {
891
              type: 'listbox',
892
              name: 'borderstyle',
893
              label: 'Border style',
894
              items: [
895
                {
896
                  text: 'Select...',
897
                  value: ''
898
                },
899
                {
900
                  text: 'Solid',
901
                  value: 'solid'
902
                },
903
                {
904
                  text: 'Dotted',
905
                  value: 'dotted'
906
                },
907
                {
908
                  text: 'Dashed',
909
                  value: 'dashed'
910
                },
911
                {
912
                  text: 'Double',
913
                  value: 'double'
914
                },
915
                {
916
                  text: 'Groove',
917
                  value: 'groove'
918
                },
919
                {
920
                  text: 'Ridge',
921
                  value: 'ridge'
922
                },
923
                {
924
                  text: 'Inset',
925
                  value: 'inset'
926
                },
927
                {
928
                  text: 'Outset',
929
                  value: 'outset'
930
                },
931
                {
932
                  text: 'None',
933
                  value: 'none'
934
                },
935
                {
936
                  text: 'Hidden',
937
                  value: 'hidden'
938
                }
939
              ]
940
            }
941
          ]
942
        }]
943
    });
944
    const AdvTab = { makeTab: makeTab$2 };
945
 
946
    const collect = editor => {
947
      const urlListSanitizer = ListUtils.sanitizer(item => editor.convertURL(item.value || item.url || '', 'src'));
948
      const futureImageList = new Promise(completer => {
949
        createImageList(editor, imageList => {
950
          completer(urlListSanitizer(imageList).map(items => flatten([
951
            [{
952
                text: 'None',
953
                value: ''
954
              }],
955
            items
956
          ])));
957
        });
958
      });
959
      const classList = ListUtils.sanitize(getClassList(editor));
960
      const hasAdvTab$1 = hasAdvTab(editor);
961
      const hasUploadTab$1 = hasUploadTab(editor);
962
      const hasUploadUrl$1 = hasUploadUrl(editor);
963
      const hasUploadHandler$1 = hasUploadHandler(editor);
964
      const image = readImageDataFromSelection(editor);
965
      const hasDescription$1 = hasDescription(editor);
966
      const hasImageTitle$1 = hasImageTitle(editor);
967
      const hasDimensions$1 = hasDimensions(editor);
968
      const hasImageCaption$1 = hasImageCaption(editor);
969
      const hasAccessibilityOptions = showAccessibilityOptions(editor);
970
      const automaticUploads = isAutomaticUploadsEnabled(editor);
971
      const prependURL = Optional.some(getPrependUrl(editor)).filter(preUrl => isString(preUrl) && preUrl.length > 0);
972
      return futureImageList.then(imageList => ({
973
        image,
974
        imageList,
975
        classList,
976
        hasAdvTab: hasAdvTab$1,
977
        hasUploadTab: hasUploadTab$1,
978
        hasUploadUrl: hasUploadUrl$1,
979
        hasUploadHandler: hasUploadHandler$1,
980
        hasDescription: hasDescription$1,
981
        hasImageTitle: hasImageTitle$1,
982
        hasDimensions: hasDimensions$1,
983
        hasImageCaption: hasImageCaption$1,
984
        prependURL,
985
        hasAccessibilityOptions,
986
        automaticUploads
987
      }));
988
    };
989
 
990
    const makeItems = info => {
991
      const imageUrl = {
992
        name: 'src',
993
        type: 'urlinput',
994
        filetype: 'image',
995
        label: 'Source',
996
        picker_text: 'Browse files'
997
      };
998
      const imageList = info.imageList.map(items => ({
999
        name: 'images',
1000
        type: 'listbox',
1001
        label: 'Image list',
1002
        items
1003
      }));
1004
      const imageDescription = {
1005
        name: 'alt',
1006
        type: 'input',
1007
        label: 'Alternative description',
1008
        enabled: !(info.hasAccessibilityOptions && info.image.isDecorative)
1009
      };
1010
      const imageTitle = {
1011
        name: 'title',
1012
        type: 'input',
1013
        label: 'Image title'
1014
      };
1015
      const imageDimensions = {
1016
        name: 'dimensions',
1017
        type: 'sizeinput'
1018
      };
1019
      const isDecorative = {
1020
        type: 'label',
1021
        label: 'Accessibility',
1022
        items: [{
1023
            name: 'isDecorative',
1024
            type: 'checkbox',
1025
            label: 'Image is decorative'
1026
          }]
1027
      };
1028
      const classList = info.classList.map(items => ({
1029
        name: 'classes',
1030
        type: 'listbox',
1031
        label: 'Class',
1032
        items
1033
      }));
1034
      const caption = {
1035
        type: 'label',
1036
        label: 'Caption',
1037
        items: [{
1038
            type: 'checkbox',
1039
            name: 'caption',
1040
            label: 'Show caption'
1041
          }]
1042
      };
1043
      const getDialogContainerType = useColumns => useColumns ? {
1044
        type: 'grid',
1045
        columns: 2
1046
      } : { type: 'panel' };
1047
      return flatten([
1048
        [imageUrl],
1049
        imageList.toArray(),
1050
        info.hasAccessibilityOptions && info.hasDescription ? [isDecorative] : [],
1051
        info.hasDescription ? [imageDescription] : [],
1052
        info.hasImageTitle ? [imageTitle] : [],
1053
        info.hasDimensions ? [imageDimensions] : [],
1054
        [{
1055
            ...getDialogContainerType(info.classList.isSome() && info.hasImageCaption),
1056
            items: flatten([
1057
              classList.toArray(),
1058
              info.hasImageCaption ? [caption] : []
1059
            ])
1060
          }]
1061
      ]);
1062
    };
1063
    const makeTab$1 = info => ({
1064
      title: 'General',
1065
      name: 'general',
1066
      items: makeItems(info)
1067
    });
1068
    const MainTab = {
1069
      makeTab: makeTab$1,
1070
      makeItems
1071
    };
1072
 
1073
    const makeTab = _info => {
1074
      const items = [{
1075
          type: 'dropzone',
1076
          name: 'fileinput'
1077
        }];
1078
      return {
1079
        title: 'Upload',
1080
        name: 'upload',
1081
        items
1082
      };
1083
    };
1084
    const UploadTab = { makeTab };
1085
 
1086
    const createState = info => ({
1087
      prevImage: ListUtils.findEntry(info.imageList, info.image.src),
1088
      prevAlt: info.image.alt,
1089
      open: true
1090
    });
1091
    const fromImageData = image => ({
1092
      src: {
1093
        value: image.src,
1094
        meta: {}
1095
      },
1096
      images: image.src,
1097
      alt: image.alt,
1098
      title: image.title,
1099
      dimensions: {
1100
        width: image.width,
1101
        height: image.height
1102
      },
1103
      classes: image.class,
1104
      caption: image.caption,
1105
      style: image.style,
1106
      vspace: image.vspace,
1107
      border: image.border,
1108
      hspace: image.hspace,
1109
      borderstyle: image.borderStyle,
1110
      fileinput: [],
1111
      isDecorative: image.isDecorative
1112
    });
1113
    const toImageData = (data, removeEmptyAlt) => ({
1114
      src: data.src.value,
1115
      alt: (data.alt === null || data.alt.length === 0) && removeEmptyAlt ? null : data.alt,
1116
      title: data.title,
1117
      width: data.dimensions.width,
1118
      height: data.dimensions.height,
1119
      class: data.classes,
1120
      style: data.style,
1121
      caption: data.caption,
1122
      hspace: data.hspace,
1123
      vspace: data.vspace,
1124
      border: data.border,
1125
      borderStyle: data.borderstyle,
1126
      isDecorative: data.isDecorative
1127
    });
1128
    const addPrependUrl2 = (info, srcURL) => {
1129
      if (!/^(?:[a-zA-Z]+:)?\/\//.test(srcURL)) {
1130
        return info.prependURL.bind(prependUrl => {
1131
          if (srcURL.substring(0, prependUrl.length) !== prependUrl) {
1132
            return Optional.some(prependUrl + srcURL);
1133
          }
1134
          return Optional.none();
1135
        });
1136
      }
1137
      return Optional.none();
1138
    };
1139
    const addPrependUrl = (info, api) => {
1140
      const data = api.getData();
1141
      addPrependUrl2(info, data.src.value).each(srcURL => {
1142
        api.setData({
1143
          src: {
1144
            value: srcURL,
1145
            meta: data.src.meta
1146
          }
1147
        });
1148
      });
1149
    };
1150
    const formFillFromMeta2 = (info, data, meta) => {
1151
      if (info.hasDescription && isString(meta.alt)) {
1152
        data.alt = meta.alt;
1153
      }
1154
      if (info.hasAccessibilityOptions) {
1155
        data.isDecorative = meta.isDecorative || data.isDecorative || false;
1156
      }
1157
      if (info.hasImageTitle && isString(meta.title)) {
1158
        data.title = meta.title;
1159
      }
1160
      if (info.hasDimensions) {
1161
        if (isString(meta.width)) {
1162
          data.dimensions.width = meta.width;
1163
        }
1164
        if (isString(meta.height)) {
1165
          data.dimensions.height = meta.height;
1166
        }
1167
      }
1168
      if (isString(meta.class)) {
1169
        ListUtils.findEntry(info.classList, meta.class).each(entry => {
1170
          data.classes = entry.value;
1171
        });
1172
      }
1173
      if (info.hasImageCaption) {
1174
        if (isBoolean(meta.caption)) {
1175
          data.caption = meta.caption;
1176
        }
1177
      }
1178
      if (info.hasAdvTab) {
1179
        if (isString(meta.style)) {
1180
          data.style = meta.style;
1181
        }
1182
        if (isString(meta.vspace)) {
1183
          data.vspace = meta.vspace;
1184
        }
1185
        if (isString(meta.border)) {
1186
          data.border = meta.border;
1187
        }
1188
        if (isString(meta.hspace)) {
1189
          data.hspace = meta.hspace;
1190
        }
1191
        if (isString(meta.borderstyle)) {
1192
          data.borderstyle = meta.borderstyle;
1193
        }
1194
      }
1195
    };
1196
    const formFillFromMeta = (info, api) => {
1197
      const data = api.getData();
1198
      const meta = data.src.meta;
1199
      if (meta !== undefined) {
1200
        const newData = deepMerge({}, data);
1201
        formFillFromMeta2(info, newData, meta);
1202
        api.setData(newData);
1203
      }
1204
    };
1205
    const calculateImageSize = (helpers, info, state, api) => {
1206
      const data = api.getData();
1207
      const url = data.src.value;
1208
      const meta = data.src.meta || {};
1209
      if (!meta.width && !meta.height && info.hasDimensions) {
1210
        if (isNotEmpty(url)) {
1211
          helpers.imageSize(url).then(size => {
1212
            if (state.open) {
1213
              api.setData({ dimensions: size });
1214
            }
1215
          }).catch(e => console.error(e));
1216
        } else {
1217
          api.setData({
1218
            dimensions: {
1219
              width: '',
1220
              height: ''
1221
            }
1222
          });
1223
        }
1224
      }
1225
    };
1226
    const updateImagesDropdown = (info, state, api) => {
1227
      const data = api.getData();
1228
      const image = ListUtils.findEntry(info.imageList, data.src.value);
1229
      state.prevImage = image;
1230
      api.setData({ images: image.map(entry => entry.value).getOr('') });
1231
    };
1232
    const changeSrc = (helpers, info, state, api) => {
1233
      addPrependUrl(info, api);
1234
      formFillFromMeta(info, api);
1235
      calculateImageSize(helpers, info, state, api);
1236
      updateImagesDropdown(info, state, api);
1237
    };
1238
    const changeImages = (helpers, info, state, api) => {
1239
      const data = api.getData();
1240
      const image = ListUtils.findEntry(info.imageList, data.images);
1241
      image.each(img => {
1242
        const updateAlt = data.alt === '' || state.prevImage.map(image => image.text === data.alt).getOr(false);
1243
        if (updateAlt) {
1244
          if (img.value === '') {
1245
            api.setData({
1246
              src: img,
1247
              alt: state.prevAlt
1248
            });
1249
          } else {
1250
            api.setData({
1251
              src: img,
1252
              alt: img.text
1253
            });
1254
          }
1255
        } else {
1256
          api.setData({ src: img });
1257
        }
1258
      });
1259
      state.prevImage = image;
1260
      changeSrc(helpers, info, state, api);
1261
    };
1262
    const changeFileInput = (helpers, info, state, api) => {
1263
      const data = api.getData();
1264
      api.block('Uploading image');
1265
      head(data.fileinput).fold(() => {
1266
        api.unblock();
1267
      }, file => {
1268
        const blobUri = URL.createObjectURL(file);
1269
        const finalize = () => {
1270
          api.unblock();
1271
          URL.revokeObjectURL(blobUri);
1272
        };
1273
        const updateSrcAndSwitchTab = url => {
1274
          api.setData({
1275
            src: {
1276
              value: url,
1277
              meta: {}
1278
            }
1279
          });
1280
          api.showTab('general');
1281
          changeSrc(helpers, info, state, api);
1282
        };
1283
        blobToDataUri(file).then(dataUrl => {
1284
          const blobInfo = helpers.createBlobCache(file, blobUri, dataUrl);
1285
          if (info.automaticUploads) {
1286
            helpers.uploadImage(blobInfo).then(result => {
1287
              updateSrcAndSwitchTab(result.url);
1288
              finalize();
1289
            }).catch(err => {
1290
              finalize();
1291
              helpers.alertErr(err);
1292
            });
1293
          } else {
1294
            helpers.addToBlobCache(blobInfo);
1295
            updateSrcAndSwitchTab(blobInfo.blobUri());
1296
            api.unblock();
1297
          }
1298
        });
1299
      });
1300
    };
1301
    const changeHandler = (helpers, info, state) => (api, evt) => {
1302
      if (evt.name === 'src') {
1303
        changeSrc(helpers, info, state, api);
1304
      } else if (evt.name === 'images') {
1305
        changeImages(helpers, info, state, api);
1306
      } else if (evt.name === 'alt') {
1307
        state.prevAlt = api.getData().alt;
1308
      } else if (evt.name === 'fileinput') {
1309
        changeFileInput(helpers, info, state, api);
1310
      } else if (evt.name === 'isDecorative') {
1311
        api.setEnabled('alt', !api.getData().isDecorative);
1312
      }
1313
    };
1314
    const closeHandler = state => () => {
1315
      state.open = false;
1316
    };
1317
    const makeDialogBody = info => {
1318
      if (info.hasAdvTab || info.hasUploadUrl || info.hasUploadHandler) {
1319
        const tabPanel = {
1320
          type: 'tabpanel',
1321
          tabs: flatten([
1322
            [MainTab.makeTab(info)],
1323
            info.hasAdvTab ? [AdvTab.makeTab(info)] : [],
1324
            info.hasUploadTab && (info.hasUploadUrl || info.hasUploadHandler) ? [UploadTab.makeTab(info)] : []
1325
          ])
1326
        };
1327
        return tabPanel;
1328
      } else {
1329
        const panel = {
1330
          type: 'panel',
1331
          items: MainTab.makeItems(info)
1332
        };
1333
        return panel;
1334
      }
1335
    };
1336
    const submitHandler = (editor, info, helpers) => api => {
1337
      const data = deepMerge(fromImageData(info.image), api.getData());
1338
      const finalData = {
1339
        ...data,
1340
        style: getStyleValue(helpers.normalizeCss, toImageData(data, false))
1341
      };
1342
      editor.execCommand('mceUpdateImage', false, toImageData(finalData, info.hasAccessibilityOptions));
1343
      editor.editorUpload.uploadImagesAuto();
1344
      api.close();
1345
    };
1346
    const imageSize = editor => url => {
1347
      if (!isSafeImageUrl(editor, url)) {
1348
        return Promise.resolve({
1349
          width: '',
1350
          height: ''
1351
        });
1352
      } else {
1353
        return getImageSize(editor.documentBaseURI.toAbsolute(url)).then(dimensions => ({
1354
          width: String(dimensions.width),
1355
          height: String(dimensions.height)
1356
        }));
1357
      }
1358
    };
1359
    const createBlobCache = editor => (file, blobUri, dataUrl) => {
1360
      var _a;
1361
      return editor.editorUpload.blobCache.create({
1362
        blob: file,
1363
        blobUri,
1364
        name: (_a = file.name) === null || _a === void 0 ? void 0 : _a.replace(/\.[^\.]+$/, ''),
1365
        filename: file.name,
1366
        base64: dataUrl.split(',')[1]
1367
      });
1368
    };
1369
    const addToBlobCache = editor => blobInfo => {
1370
      editor.editorUpload.blobCache.add(blobInfo);
1371
    };
1372
    const alertErr = editor => message => {
1373
      editor.windowManager.alert(message);
1374
    };
1375
    const normalizeCss = editor => cssText => normalizeCss$1(editor, cssText);
1376
    const parseStyle = editor => cssText => editor.dom.parseStyle(cssText);
1377
    const serializeStyle = editor => (stylesArg, name) => editor.dom.serializeStyle(stylesArg, name);
1378
    const uploadImage = editor => blobInfo => global$1(editor).upload([blobInfo], false).then(results => {
1379
      var _a;
1380
      if (results.length === 0) {
1381
        return Promise.reject('Failed to upload image');
1382
      } else if (results[0].status === false) {
1383
        return Promise.reject((_a = results[0].error) === null || _a === void 0 ? void 0 : _a.message);
1384
      } else {
1385
        return results[0];
1386
      }
1387
    });
1388
    const Dialog = editor => {
1389
      const helpers = {
1390
        imageSize: imageSize(editor),
1391
        addToBlobCache: addToBlobCache(editor),
1392
        createBlobCache: createBlobCache(editor),
1393
        alertErr: alertErr(editor),
1394
        normalizeCss: normalizeCss(editor),
1395
        parseStyle: parseStyle(editor),
1396
        serializeStyle: serializeStyle(editor),
1397
        uploadImage: uploadImage(editor)
1398
      };
1399
      const open = () => {
1400
        collect(editor).then(info => {
1401
          const state = createState(info);
1402
          return {
1403
            title: 'Insert/Edit Image',
1404
            size: 'normal',
1405
            body: makeDialogBody(info),
1406
            buttons: [
1407
              {
1408
                type: 'cancel',
1409
                name: 'cancel',
1410
                text: 'Cancel'
1411
              },
1412
              {
1413
                type: 'submit',
1414
                name: 'save',
1415
                text: 'Save',
1416
                primary: true
1417
              }
1418
            ],
1419
            initialData: fromImageData(info.image),
1420
            onSubmit: submitHandler(editor, info, helpers),
1421
            onChange: changeHandler(helpers, info, state),
1422
            onClose: closeHandler(state)
1423
          };
1424
        }).then(editor.windowManager.open);
1425
      };
1426
      return { open };
1427
    };
1428
 
1429
    const register$1 = editor => {
1430
      editor.addCommand('mceImage', Dialog(editor).open);
1431
      editor.addCommand('mceUpdateImage', (_ui, data) => {
1432
        editor.undoManager.transact(() => insertOrUpdateImage(editor, data));
1433
      });
1434
    };
1435
 
1436
    const hasImageClass = node => {
1437
      const className = node.attr('class');
1438
      return isNonNullable(className) && /\bimage\b/.test(className);
1439
    };
1440
    const toggleContentEditableState = state => nodes => {
1441
      let i = nodes.length;
1442
      const toggleContentEditable = node => {
1443
        node.attr('contenteditable', state ? 'true' : null);
1444
      };
1445
      while (i--) {
1446
        const node = nodes[i];
1447
        if (hasImageClass(node)) {
1448
          node.attr('contenteditable', state ? 'false' : null);
1449
          global.each(node.getAll('figcaption'), toggleContentEditable);
1450
        }
1451
      }
1452
    };
1453
    const setup = editor => {
1454
      editor.on('PreInit', () => {
1455
        editor.parser.addNodeFilter('figure', toggleContentEditableState(true));
1456
        editor.serializer.addNodeFilter('figure', toggleContentEditableState(false));
1457
      });
1458
    };
1459
 
1460
    const onSetupEditable = editor => api => {
1461
      const nodeChanged = () => {
1462
        api.setEnabled(editor.selection.isEditable());
1463
      };
1464
      editor.on('NodeChange', nodeChanged);
1465
      nodeChanged();
1466
      return () => {
1467
        editor.off('NodeChange', nodeChanged);
1468
      };
1469
    };
1470
    const register = editor => {
1471
      editor.ui.registry.addToggleButton('image', {
1472
        icon: 'image',
1473
        tooltip: 'Insert/edit image',
1474
        onAction: Dialog(editor).open,
1475
        onSetup: buttonApi => {
1476
          buttonApi.setActive(isNonNullable(getSelectedImage(editor)));
1477
          const unbindSelectorChanged = editor.selection.selectorChangedWithUnbind('img:not([data-mce-object]):not([data-mce-placeholder]),figure.image', buttonApi.setActive).unbind;
1478
          const unbindEditable = onSetupEditable(editor)(buttonApi);
1479
          return () => {
1480
            unbindSelectorChanged();
1481
            unbindEditable();
1482
          };
1483
        }
1484
      });
1485
      editor.ui.registry.addMenuItem('image', {
1486
        icon: 'image',
1487
        text: 'Image...',
1488
        onAction: Dialog(editor).open,
1489
        onSetup: onSetupEditable(editor)
1490
      });
1491
      editor.ui.registry.addContextMenu('image', { update: element => editor.selection.isEditable() && (isFigure(element) || isImage(element) && !isPlaceholderImage(element)) ? ['image'] : [] });
1492
    };
1493
 
1494
    var Plugin = () => {
1495
      global$4.add('image', editor => {
1496
        register$2(editor);
1497
        setup(editor);
1498
        register(editor);
1499
        register$1(editor);
1500
      });
1501
    };
1502
 
1503
    Plugin();
1504
 
1505
})();