fx-platform-ui 0.0.13-alpha14 → 0.0.13-alpha15

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