@dangl/angular-material-shared 2.9.0-beta0037 → 2.9.0-beta0040
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.
- package/fesm2022/dangl-angular-material-shared-tiny-mce.mjs +29 -35
- package/fesm2022/dangl-angular-material-shared-tiny-mce.mjs.map +1 -1
- package/fesm2022/dangl-angular-material-shared.mjs +36 -51
- package/fesm2022/dangl-angular-material-shared.mjs.map +1 -1
- package/package.json +11 -10
- package/styles/material-theme.scss +1 -1
- package/styles/material-variables.scss +5 -5
- package/tinymce-assets/icons/default/icons.js +46 -9
- package/tinymce-assets/icons/default/icons.min.js +1 -1
- package/tinymce-assets/models/dom/model.js +8198 -7244
- package/tinymce-assets/models/dom/model.min.js +1 -4
- package/tinymce-assets/plugins/accordion/plugin.js +1174 -879
- package/tinymce-assets/plugins/accordion/plugin.min.js +1 -4
- package/tinymce-assets/plugins/advlist/plugin.js +412 -200
- package/tinymce-assets/plugins/advlist/plugin.min.js +1 -4
- package/tinymce-assets/plugins/anchor/plugin.js +189 -166
- package/tinymce-assets/plugins/anchor/plugin.min.js +1 -4
- package/tinymce-assets/plugins/autolink/plugin.js +310 -220
- package/tinymce-assets/plugins/autolink/plugin.min.js +1 -4
- package/tinymce-assets/plugins/autoresize/plugin.js +180 -149
- package/tinymce-assets/plugins/autoresize/plugin.min.js +1 -4
- package/tinymce-assets/plugins/autosave/plugin.js +208 -189
- package/tinymce-assets/plugins/autosave/plugin.min.js +1 -4
- package/tinymce-assets/plugins/charmap/plugin.js +905 -1566
- package/tinymce-assets/plugins/charmap/plugin.min.js +1 -4
- package/tinymce-assets/plugins/code/plugin.js +73 -61
- package/tinymce-assets/plugins/code/plugin.min.js +0 -3
- package/tinymce-assets/plugins/codesample/plugin.js +3593 -2402
- package/tinymce-assets/plugins/codesample/plugin.min.js +8 -3
- package/tinymce-assets/plugins/directionality/plugin.js +545 -304
- package/tinymce-assets/plugins/directionality/plugin.min.js +1 -4
- package/tinymce-assets/plugins/emoticons/js/emojiimages.min.js +0 -2
- package/tinymce-assets/plugins/emoticons/js/emojis.min.js +0 -1
- package/tinymce-assets/plugins/emoticons/plugin.js +702 -488
- package/tinymce-assets/plugins/emoticons/plugin.min.js +1 -4
- package/tinymce-assets/plugins/fullscreen/plugin.js +1409 -1049
- package/tinymce-assets/plugins/fullscreen/plugin.min.js +1 -4
- package/tinymce-assets/plugins/help/js/i18n/keynav/ar.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/bg_BG.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ca.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/cs.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/da.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/de.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/el.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/en.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/es.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/eu.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/fa.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/fi.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/fr_FR.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/he_IL.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/hi.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/hr.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/hu_HU.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/id.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/it.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ja.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/kk.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ko_KR.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ms.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/nb_NO.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/nl.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/pl.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/pt_BR.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/pt_PT.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ro.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ru.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/sk.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/sl_SI.js +5 -2
- package/tinymce-assets/plugins/help/js/i18n/keynav/sv_SE.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/th_TH.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/tr.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/uk.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/vi.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/zh_CN.js +8 -5
- package/tinymce-assets/plugins/help/js/i18n/keynav/zh_TW.js +4 -1
- package/tinymce-assets/plugins/help/plugin.js +739 -809
- package/tinymce-assets/plugins/help/plugin.min.js +1 -4
- package/tinymce-assets/plugins/image/plugin.js +1475 -1291
- package/tinymce-assets/plugins/image/plugin.min.js +1 -4
- package/tinymce-assets/plugins/importcss/plugin.js +328 -269
- package/tinymce-assets/plugins/importcss/plugin.min.js +1 -4
- package/tinymce-assets/plugins/insertdatetime/plugin.js +140 -141
- package/tinymce-assets/plugins/insertdatetime/plugin.min.js +1 -4
- package/tinymce-assets/plugins/link/plugin.js +1419 -1084
- package/tinymce-assets/plugins/link/plugin.min.js +1 -4
- package/tinymce-assets/plugins/lists/plugin.js +2177 -1805
- package/tinymce-assets/plugins/lists/plugin.min.js +1 -4
- package/tinymce-assets/plugins/media/plugin.js +1305 -1047
- package/tinymce-assets/plugins/media/plugin.min.js +1 -4
- package/tinymce-assets/plugins/nonbreaking/plugin.js +93 -88
- package/tinymce-assets/plugins/nonbreaking/plugin.min.js +0 -3
- package/tinymce-assets/plugins/pagebreak/plugin.js +91 -85
- package/tinymce-assets/plugins/pagebreak/plugin.min.js +0 -3
- package/tinymce-assets/plugins/preview/plugin.js +742 -74
- package/tinymce-assets/plugins/preview/plugin.min.js +1 -4
- package/tinymce-assets/plugins/quickbars/plugin.js +582 -375
- package/tinymce-assets/plugins/quickbars/plugin.min.js +1 -4
- package/tinymce-assets/plugins/save/plugin.js +100 -82
- package/tinymce-assets/plugins/save/plugin.min.js +1 -4
- package/tinymce-assets/plugins/searchreplace/plugin.js +1183 -906
- package/tinymce-assets/plugins/searchreplace/plugin.min.js +1 -4
- package/tinymce-assets/plugins/table/plugin.js +3651 -3094
- package/tinymce-assets/plugins/table/plugin.min.js +1 -4
- package/tinymce-assets/plugins/visualblocks/plugin.js +71 -63
- package/tinymce-assets/plugins/visualblocks/plugin.min.js +1 -4
- package/tinymce-assets/plugins/visualchars/plugin.js +685 -436
- package/tinymce-assets/plugins/visualchars/plugin.min.js +1 -4
- package/tinymce-assets/plugins/wordcount/plugin.js +382 -307
- package/tinymce-assets/plugins/wordcount/plugin.min.js +1 -4
- package/tinymce-assets/skins/content/dark/content.css +9 -0
- package/tinymce-assets/skins/content/dark/content.js +10 -2
- package/tinymce-assets/skins/content/dark/content.min.css +9 -0
- package/tinymce-assets/skins/content/default/content.css +9 -0
- package/tinymce-assets/skins/content/default/content.js +10 -2
- package/tinymce-assets/skins/content/default/content.min.css +9 -0
- package/tinymce-assets/skins/content/document/content.css +9 -0
- package/tinymce-assets/skins/content/document/content.js +10 -2
- package/tinymce-assets/skins/content/document/content.min.css +9 -0
- package/tinymce-assets/skins/content/tinymce-5/content.css +9 -0
- package/tinymce-assets/skins/content/tinymce-5/content.js +10 -2
- package/tinymce-assets/skins/content/tinymce-5/content.min.css +9 -0
- package/tinymce-assets/skins/content/tinymce-5-dark/content.css +9 -0
- package/tinymce-assets/skins/content/tinymce-5-dark/content.js +10 -2
- package/tinymce-assets/skins/content/tinymce-5-dark/content.min.css +9 -0
- package/tinymce-assets/skins/content/writer/content.css +9 -0
- package/tinymce-assets/skins/content/writer/content.js +10 -2
- package/tinymce-assets/skins/content/writer/content.min.css +9 -0
- package/tinymce-assets/skins/ui/oxide/content.css +157 -49
- package/tinymce-assets/skins/ui/oxide/content.inline.css +157 -49
- package/tinymce-assets/skins/ui/oxide/content.inline.js +10 -2
- package/tinymce-assets/skins/ui/oxide/content.inline.min.css +10 -1
- package/tinymce-assets/skins/ui/oxide/content.js +10 -2
- package/tinymce-assets/skins/ui/oxide/content.min.css +10 -1
- package/tinymce-assets/skins/ui/oxide/skin.css +1592 -214
- package/tinymce-assets/skins/ui/oxide/skin.js +1 -2
- package/tinymce-assets/skins/ui/oxide/skin.min.css +1 -1
- package/tinymce-assets/skins/ui/oxide/skin.shadowdom.js +1 -2
- package/tinymce-assets/skins/ui/oxide-dark/content.css +157 -42
- package/tinymce-assets/skins/ui/oxide-dark/content.inline.css +157 -49
- package/tinymce-assets/skins/ui/oxide-dark/content.inline.js +10 -2
- package/tinymce-assets/skins/ui/oxide-dark/content.inline.min.css +10 -1
- package/tinymce-assets/skins/ui/oxide-dark/content.js +10 -2
- package/tinymce-assets/skins/ui/oxide-dark/content.min.css +10 -1
- package/tinymce-assets/skins/ui/oxide-dark/skin.css +1595 -217
- package/tinymce-assets/skins/ui/oxide-dark/skin.js +1 -2
- package/tinymce-assets/skins/ui/oxide-dark/skin.min.css +1 -1
- package/tinymce-assets/skins/ui/oxide-dark/skin.shadowdom.js +1 -2
- package/tinymce-assets/skins/ui/tinymce-5/content.css +157 -49
- package/tinymce-assets/skins/ui/tinymce-5/content.inline.css +157 -49
- package/tinymce-assets/skins/ui/tinymce-5/content.inline.js +10 -2
- package/tinymce-assets/skins/ui/tinymce-5/content.inline.min.css +10 -1
- package/tinymce-assets/skins/ui/tinymce-5/content.js +10 -2
- package/tinymce-assets/skins/ui/tinymce-5/content.min.css +10 -1
- package/tinymce-assets/skins/ui/tinymce-5/skin.css +1606 -203
- package/tinymce-assets/skins/ui/tinymce-5/skin.js +1 -2
- package/tinymce-assets/skins/ui/tinymce-5/skin.min.css +1 -1
- package/tinymce-assets/skins/ui/tinymce-5/skin.shadowdom.js +1 -2
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.css +157 -42
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.inline.css +157 -49
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.inline.js +10 -2
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.inline.min.css +10 -1
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.js +10 -2
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.min.css +10 -1
- package/tinymce-assets/skins/ui/tinymce-5-dark/skin.css +1607 -204
- package/tinymce-assets/skins/ui/tinymce-5-dark/skin.js +1 -2
- package/tinymce-assets/skins/ui/tinymce-5-dark/skin.min.css +1 -1
- package/tinymce-assets/skins/ui/tinymce-5-dark/skin.shadowdom.js +1 -2
- package/tinymce-assets/themes/silver/theme.js +32786 -28738
- package/tinymce-assets/themes/silver/theme.min.js +1 -4
- package/types/dangl-angular-material-shared-tiny-mce.d.ts +12 -13
- package/types/dangl-angular-material-shared.d.ts +26 -26
- package/tinymce-assets/plugins/template/index.js +0 -7
- package/tinymce-assets/plugins/template/plugin.js +0 -567
- package/tinymce-assets/plugins/template/plugin.min.js +0 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TinyMCE version
|
|
2
|
+
* TinyMCE version 7.9.3 (2026-05-19)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
(function () {
|
|
@@ -7,200 +7,400 @@
|
|
|
7
7
|
|
|
8
8
|
var global$6 = tinymce.util.Tools.resolve('tinymce.PluginManager');
|
|
9
9
|
|
|
10
|
+
/* eslint-disable @typescript-eslint/no-wrapper-object-types */
|
|
10
11
|
const hasProto = (v, constructor, predicate) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
var _a;
|
|
13
|
+
if (predicate(v, constructor.prototype)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
// String-based fallback time
|
|
18
|
+
return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
|
|
19
|
+
}
|
|
17
20
|
};
|
|
18
|
-
const typeOf = x => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
const typeOf = (x) => {
|
|
22
|
+
const t = typeof x;
|
|
23
|
+
if (x === null) {
|
|
24
|
+
return 'null';
|
|
25
|
+
}
|
|
26
|
+
else if (t === 'object' && Array.isArray(x)) {
|
|
27
|
+
return 'array';
|
|
28
|
+
}
|
|
29
|
+
else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
|
|
30
|
+
return 'string';
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
return t;
|
|
34
|
+
}
|
|
29
35
|
};
|
|
30
|
-
const isType = type => value => typeOf(value) === type;
|
|
36
|
+
const isType = (type) => (value) => typeOf(value) === type;
|
|
37
|
+
const isSimpleType = (type) => (value) => typeof value === type;
|
|
31
38
|
const isString = isType('string');
|
|
32
39
|
const isObject = isType('object');
|
|
33
40
|
const isArray = isType('array');
|
|
34
|
-
const isNullable = a => a === null || a === undefined;
|
|
35
|
-
const isNonNullable = a => !isNullable(a);
|
|
41
|
+
const isNullable = (a) => a === null || a === undefined;
|
|
42
|
+
const isNonNullable = (a) => !isNullable(a);
|
|
43
|
+
const isFunction = isSimpleType('function');
|
|
36
44
|
|
|
45
|
+
/**
|
|
46
|
+
* The `Optional` type represents a value (of any type) that potentially does
|
|
47
|
+
* not exist. Any `Optional<T>` can either be a `Some<T>` (in which case the
|
|
48
|
+
* value does exist) or a `None` (in which case the value does not exist). This
|
|
49
|
+
* module defines a whole lot of FP-inspired utility functions for dealing with
|
|
50
|
+
* `Optional` objects.
|
|
51
|
+
*
|
|
52
|
+
* Comparison with null or undefined:
|
|
53
|
+
* - We don't get fancy null coalescing operators with `Optional`
|
|
54
|
+
* - We do get fancy helper functions with `Optional`
|
|
55
|
+
* - `Optional` support nesting, and allow for the type to still be nullable (or
|
|
56
|
+
* another `Optional`)
|
|
57
|
+
* - There is no option to turn off strict-optional-checks like there is for
|
|
58
|
+
* strict-null-checks
|
|
59
|
+
*/
|
|
37
60
|
class Optional {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
61
|
+
// The internal representation has a `tag` and a `value`, but both are
|
|
62
|
+
// private: able to be console.logged, but not able to be accessed by code
|
|
63
|
+
constructor(tag, value) {
|
|
64
|
+
this.tag = tag;
|
|
65
|
+
this.value = value;
|
|
66
|
+
}
|
|
67
|
+
// --- Identities ---
|
|
68
|
+
/**
|
|
69
|
+
* Creates a new `Optional<T>` that **does** contain a value.
|
|
70
|
+
*/
|
|
71
|
+
static some(value) {
|
|
72
|
+
return new Optional(true, value);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create a new `Optional<T>` that **does not** contain a value. `T` can be
|
|
76
|
+
* any type because we don't actually have a `T`.
|
|
77
|
+
*/
|
|
78
|
+
static none() {
|
|
79
|
+
return Optional.singletonNone;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Perform a transform on an `Optional` type. Regardless of whether this
|
|
83
|
+
* `Optional` contains a value or not, `fold` will return a value of type `U`.
|
|
84
|
+
* If this `Optional` does not contain a value, the `U` will be created by
|
|
85
|
+
* calling `onNone`. If this `Optional` does contain a value, the `U` will be
|
|
86
|
+
* created by calling `onSome`.
|
|
87
|
+
*
|
|
88
|
+
* For the FP enthusiasts in the room, this function:
|
|
89
|
+
* 1. Could be used to implement all of the functions below
|
|
90
|
+
* 2. Forms a catamorphism
|
|
91
|
+
*/
|
|
92
|
+
fold(onNone, onSome) {
|
|
93
|
+
if (this.tag) {
|
|
94
|
+
return onSome(this.value);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
return onNone();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Determine if this `Optional` object contains a value.
|
|
102
|
+
*/
|
|
103
|
+
isSome() {
|
|
104
|
+
return this.tag;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Determine if this `Optional` object **does not** contain a value.
|
|
108
|
+
*/
|
|
109
|
+
isNone() {
|
|
110
|
+
return !this.tag;
|
|
111
|
+
}
|
|
112
|
+
// --- Functor (name stolen from Haskell / maths) ---
|
|
113
|
+
/**
|
|
114
|
+
* Perform a transform on an `Optional` object, **if** there is a value. If
|
|
115
|
+
* you provide a function to turn a T into a U, this is the function you use
|
|
116
|
+
* to turn an `Optional<T>` into an `Optional<U>`. If this **does** contain
|
|
117
|
+
* a value then the output will also contain a value (that value being the
|
|
118
|
+
* output of `mapper(this.value)`), and if this **does not** contain a value
|
|
119
|
+
* then neither will the output.
|
|
120
|
+
*/
|
|
121
|
+
map(mapper) {
|
|
122
|
+
if (this.tag) {
|
|
123
|
+
return Optional.some(mapper(this.value));
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
return Optional.none();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// --- Monad (name stolen from Haskell / maths) ---
|
|
130
|
+
/**
|
|
131
|
+
* Perform a transform on an `Optional` object, **if** there is a value.
|
|
132
|
+
* Unlike `map`, here the transform itself also returns an `Optional`.
|
|
133
|
+
*/
|
|
134
|
+
bind(binder) {
|
|
135
|
+
if (this.tag) {
|
|
136
|
+
return binder(this.value);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
return Optional.none();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// --- Traversable (name stolen from Haskell / maths) ---
|
|
143
|
+
/**
|
|
144
|
+
* For a given predicate, this function finds out if there **exists** a value
|
|
145
|
+
* inside this `Optional` object that meets the predicate. In practice, this
|
|
146
|
+
* means that for `Optional`s that do not contain a value it returns false (as
|
|
147
|
+
* no predicate-meeting value exists).
|
|
148
|
+
*/
|
|
149
|
+
exists(predicate) {
|
|
150
|
+
return this.tag && predicate(this.value);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* For a given predicate, this function finds out if **all** the values inside
|
|
154
|
+
* this `Optional` object meet the predicate. In practice, this means that
|
|
155
|
+
* for `Optional`s that do not contain a value it returns true (as all 0
|
|
156
|
+
* objects do meet the predicate).
|
|
157
|
+
*/
|
|
158
|
+
forall(predicate) {
|
|
159
|
+
return !this.tag || predicate(this.value);
|
|
160
|
+
}
|
|
161
|
+
filter(predicate) {
|
|
162
|
+
if (!this.tag || predicate(this.value)) {
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
return Optional.none();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// --- Getters ---
|
|
170
|
+
/**
|
|
171
|
+
* Get the value out of the inside of the `Optional` object, using a default
|
|
172
|
+
* `replacement` value if the provided `Optional` object does not contain a
|
|
173
|
+
* value.
|
|
174
|
+
*/
|
|
175
|
+
getOr(replacement) {
|
|
176
|
+
return this.tag ? this.value : replacement;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get the value out of the inside of the `Optional` object, using a default
|
|
180
|
+
* `replacement` value if the provided `Optional` object does not contain a
|
|
181
|
+
* value. Unlike `getOr`, in this method the `replacement` object is also
|
|
182
|
+
* `Optional` - meaning that this method will always return an `Optional`.
|
|
183
|
+
*/
|
|
184
|
+
or(replacement) {
|
|
185
|
+
return this.tag ? this : replacement;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get the value out of the inside of the `Optional` object, using a default
|
|
189
|
+
* `replacement` value if the provided `Optional` object does not contain a
|
|
190
|
+
* value. Unlike `getOr`, in this method the `replacement` value is
|
|
191
|
+
* "thunked" - that is to say that you don't pass a value to `getOrThunk`, you
|
|
192
|
+
* pass a function which (if called) will **return** the `value` you want to
|
|
193
|
+
* use.
|
|
194
|
+
*/
|
|
195
|
+
getOrThunk(thunk) {
|
|
196
|
+
return this.tag ? this.value : thunk();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get the value out of the inside of the `Optional` object, using a default
|
|
200
|
+
* `replacement` value if the provided Optional object does not contain a
|
|
201
|
+
* value.
|
|
202
|
+
*
|
|
203
|
+
* Unlike `or`, in this method the `replacement` value is "thunked" - that is
|
|
204
|
+
* to say that you don't pass a value to `orThunk`, you pass a function which
|
|
205
|
+
* (if called) will **return** the `value` you want to use.
|
|
206
|
+
*
|
|
207
|
+
* Unlike `getOrThunk`, in this method the `replacement` value is also
|
|
208
|
+
* `Optional`, meaning that this method will always return an `Optional`.
|
|
209
|
+
*/
|
|
210
|
+
orThunk(thunk) {
|
|
211
|
+
return this.tag ? this : thunk();
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get the value out of the inside of the `Optional` object, throwing an
|
|
215
|
+
* exception if the provided `Optional` object does not contain a value.
|
|
216
|
+
*
|
|
217
|
+
* WARNING:
|
|
218
|
+
* You should only be using this function if you know that the `Optional`
|
|
219
|
+
* object **is not** empty (otherwise you're throwing exceptions in production
|
|
220
|
+
* code, which is bad).
|
|
221
|
+
*
|
|
222
|
+
* In tests this is more acceptable.
|
|
223
|
+
*
|
|
224
|
+
* Prefer other methods to this, such as `.each`.
|
|
225
|
+
*/
|
|
226
|
+
getOrDie(message) {
|
|
227
|
+
if (!this.tag) {
|
|
228
|
+
throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
return this.value;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// --- Interop with null and undefined ---
|
|
235
|
+
/**
|
|
236
|
+
* Creates an `Optional` value from a nullable (or undefined-able) input.
|
|
237
|
+
* Null, or undefined, is converted to `None`, and anything else is converted
|
|
238
|
+
* to `Some`.
|
|
239
|
+
*/
|
|
240
|
+
static from(value) {
|
|
241
|
+
return isNonNullable(value) ? Optional.some(value) : Optional.none();
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Converts an `Optional` to a nullable type, by getting the value if it
|
|
245
|
+
* exists, or returning `null` if it does not.
|
|
246
|
+
*/
|
|
247
|
+
getOrNull() {
|
|
248
|
+
return this.tag ? this.value : null;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Converts an `Optional` to an undefined-able type, by getting the value if
|
|
252
|
+
* it exists, or returning `undefined` if it does not.
|
|
253
|
+
*/
|
|
254
|
+
getOrUndefined() {
|
|
255
|
+
return this.value;
|
|
256
|
+
}
|
|
257
|
+
// --- Utilities ---
|
|
258
|
+
/**
|
|
259
|
+
* If the `Optional` contains a value, perform an action on that value.
|
|
260
|
+
* Unlike the rest of the methods on this type, `.each` has side-effects. If
|
|
261
|
+
* you want to transform an `Optional<T>` **into** something, then this is not
|
|
262
|
+
* the method for you. If you want to use an `Optional<T>` to **do**
|
|
263
|
+
* something, then this is the method for you - provided you're okay with not
|
|
264
|
+
* doing anything in the case where the `Optional` doesn't have a value inside
|
|
265
|
+
* it. If you're not sure whether your use-case fits into transforming
|
|
266
|
+
* **into** something or **doing** something, check whether it has a return
|
|
267
|
+
* value. If it does, you should be performing a transform.
|
|
268
|
+
*/
|
|
269
|
+
each(worker) {
|
|
270
|
+
if (this.tag) {
|
|
271
|
+
worker(this.value);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Turn the `Optional` object into an array that contains all of the values
|
|
276
|
+
* stored inside the `Optional`. In practice, this means the output will have
|
|
277
|
+
* either 0 or 1 elements.
|
|
278
|
+
*/
|
|
279
|
+
toArray() {
|
|
280
|
+
return this.tag ? [this.value] : [];
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Turn the `Optional` object into a string for debugging or printing. Not
|
|
284
|
+
* recommended for production code, but good for debugging. Also note that
|
|
285
|
+
* these days an `Optional` object can be logged to the console directly, and
|
|
286
|
+
* its inner value (if it exists) will be visible.
|
|
287
|
+
*/
|
|
288
|
+
toString() {
|
|
289
|
+
return this.tag ? `some(${this.value})` : 'none()';
|
|
290
|
+
}
|
|
127
291
|
}
|
|
292
|
+
// Sneaky optimisation: every instance of Optional.none is identical, so just
|
|
293
|
+
// reuse the same object
|
|
128
294
|
Optional.singletonNone = new Optional(false);
|
|
129
295
|
|
|
296
|
+
/* eslint-disable @typescript-eslint/unbound-method */
|
|
297
|
+
const nativeSlice = Array.prototype.slice;
|
|
130
298
|
const nativePush = Array.prototype.push;
|
|
299
|
+
// Unwound implementing other functions in terms of each.
|
|
300
|
+
// The code size is roughly the same, and it should allow for better optimisation.
|
|
301
|
+
// const each = function<T, U>(xs: T[], f: (x: T, i?: number, xs?: T[]) => void): void {
|
|
131
302
|
const each$1 = (xs, f) => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
};
|
|
137
|
-
const flatten = xs => {
|
|
138
|
-
const r = [];
|
|
139
|
-
for (let i = 0, len = xs.length; i < len; ++i) {
|
|
140
|
-
if (!isArray(xs[i])) {
|
|
141
|
-
throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
|
|
142
|
-
}
|
|
143
|
-
nativePush.apply(r, xs[i]);
|
|
144
|
-
}
|
|
145
|
-
return r;
|
|
303
|
+
for (let i = 0, len = xs.length; i < len; i++) {
|
|
304
|
+
const x = xs[i];
|
|
305
|
+
f(x, i);
|
|
306
|
+
}
|
|
146
307
|
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
308
|
+
const flatten = (xs) => {
|
|
309
|
+
// Note, this is possible because push supports multiple arguments:
|
|
310
|
+
// http://jsperf.com/concat-push/6
|
|
311
|
+
// Note that in the past, concat() would silently work (very slowly) for array-like objects.
|
|
312
|
+
// With this change it will throw an error.
|
|
313
|
+
const r = [];
|
|
314
|
+
for (let i = 0, len = xs.length; i < len; ++i) {
|
|
315
|
+
// Ensure that each value is an array itself
|
|
316
|
+
if (!isArray(xs[i])) {
|
|
317
|
+
throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
|
|
318
|
+
}
|
|
319
|
+
nativePush.apply(r, xs[i]);
|
|
320
|
+
}
|
|
321
|
+
return r;
|
|
160
322
|
};
|
|
323
|
+
isFunction(Array.from) ? Array.from : (x) => nativeSlice.call(x);
|
|
161
324
|
|
|
325
|
+
// There are many variations of Object iteration that are faster than the 'for-in' style:
|
|
326
|
+
// http://jsperf.com/object-keys-iteration/107
|
|
327
|
+
//
|
|
328
|
+
// Use the native keys if it is available (IE9+), otherwise fall back to manually filtering
|
|
162
329
|
const keys = Object.keys;
|
|
330
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
163
331
|
const hasOwnProperty = Object.hasOwnProperty;
|
|
164
332
|
const each = (obj, f) => {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
333
|
+
const props = keys(obj);
|
|
334
|
+
for (let k = 0, len = props.length; k < len; k++) {
|
|
335
|
+
const i = props[k];
|
|
336
|
+
const x = obj[i];
|
|
337
|
+
f(x, i);
|
|
338
|
+
}
|
|
171
339
|
};
|
|
172
340
|
const get$1 = (obj, key) => {
|
|
173
|
-
|
|
341
|
+
return has(obj, key) ? Optional.from(obj[key]) : Optional.none();
|
|
174
342
|
};
|
|
175
343
|
const has = (obj, key) => hasOwnProperty.call(obj, key);
|
|
176
344
|
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
345
|
+
const Cell = (initial) => {
|
|
346
|
+
let value = initial;
|
|
347
|
+
const get = () => {
|
|
348
|
+
return value;
|
|
349
|
+
};
|
|
350
|
+
const set = (v) => {
|
|
351
|
+
value = v;
|
|
352
|
+
};
|
|
353
|
+
return {
|
|
354
|
+
get,
|
|
355
|
+
set
|
|
356
|
+
};
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
|
|
360
|
+
/** Does 'str' start with 'prefix'?
|
|
361
|
+
* Note: all strings start with the empty string.
|
|
362
|
+
* More formally, for all strings x, startsWith(x, "").
|
|
363
|
+
* This is so that for all strings x and y, startsWith(y + x, y)
|
|
364
|
+
*/
|
|
365
|
+
const startsWith = (str, prefix) => {
|
|
366
|
+
return checkRange(str, prefix, 0);
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const option = (name) => (editor) => editor.options.get(name);
|
|
370
|
+
const register$2 = (editor) => {
|
|
371
|
+
const registerOption = editor.options.register;
|
|
372
|
+
registerOption('audio_template_callback', {
|
|
373
|
+
processor: 'function'
|
|
374
|
+
});
|
|
375
|
+
registerOption('video_template_callback', {
|
|
376
|
+
processor: 'function'
|
|
377
|
+
});
|
|
378
|
+
registerOption('iframe_template_callback', {
|
|
379
|
+
processor: 'function'
|
|
380
|
+
});
|
|
381
|
+
registerOption('media_live_embeds', {
|
|
382
|
+
processor: 'boolean',
|
|
383
|
+
default: true
|
|
384
|
+
});
|
|
385
|
+
registerOption('media_filter_html', {
|
|
386
|
+
processor: 'boolean',
|
|
387
|
+
default: true
|
|
388
|
+
});
|
|
389
|
+
registerOption('media_url_resolver', {
|
|
390
|
+
processor: 'function'
|
|
391
|
+
});
|
|
392
|
+
registerOption('media_alt_source', {
|
|
393
|
+
processor: 'boolean',
|
|
394
|
+
default: true
|
|
395
|
+
});
|
|
396
|
+
registerOption('media_poster', {
|
|
397
|
+
processor: 'boolean',
|
|
398
|
+
default: true
|
|
399
|
+
});
|
|
400
|
+
registerOption('media_dimensions', {
|
|
401
|
+
processor: 'boolean',
|
|
402
|
+
default: true
|
|
403
|
+
});
|
|
204
404
|
};
|
|
205
405
|
const getAudioTemplateCallback = option('audio_template_callback');
|
|
206
406
|
const getVideoTemplateCallback = option('video_template_callback');
|
|
@@ -219,74 +419,75 @@
|
|
|
219
419
|
var global$3 = tinymce.util.Tools.resolve('tinymce.html.DomParser');
|
|
220
420
|
|
|
221
421
|
const DOM$1 = global$4.DOM;
|
|
222
|
-
const trimPx = value => value.replace(/px$/, '');
|
|
223
|
-
const getEphoxEmbedData = node => {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
422
|
+
const trimPx = (value) => value.replace(/px$/, '');
|
|
423
|
+
const getEphoxEmbedData = (node) => {
|
|
424
|
+
const style = node.attr('style');
|
|
425
|
+
const styles = style ? DOM$1.parseStyle(style) : {};
|
|
426
|
+
return {
|
|
427
|
+
type: 'ephox-embed-iri',
|
|
428
|
+
source: node.attr('data-ephox-embed-iri'),
|
|
429
|
+
altsource: '',
|
|
430
|
+
poster: '',
|
|
431
|
+
width: get$1(styles, 'max-width').map(trimPx).getOr(''),
|
|
432
|
+
height: get$1(styles, 'max-height').map(trimPx).getOr('')
|
|
433
|
+
};
|
|
234
434
|
};
|
|
235
435
|
const htmlToData = (html, schema) => {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
436
|
+
let data = {};
|
|
437
|
+
const parser = global$3({ validate: false, forced_root_block: false }, schema);
|
|
438
|
+
const rootNode = parser.parse(html);
|
|
439
|
+
for (let node = rootNode; node; node = node.walk()) {
|
|
440
|
+
if (node.type === 1) {
|
|
441
|
+
const name = node.name;
|
|
442
|
+
if (node.attr('data-ephox-embed-iri')) {
|
|
443
|
+
data = getEphoxEmbedData(node);
|
|
444
|
+
// Don't continue to collect if we find an EME embed
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
if (!data.source && name === 'param') {
|
|
449
|
+
data.source = node.attr('movie');
|
|
450
|
+
}
|
|
451
|
+
if (name === 'iframe' || name === 'object' || name === 'embed' || name === 'video' || name === 'audio') {
|
|
452
|
+
if (!data.type) {
|
|
453
|
+
data.type = name;
|
|
454
|
+
}
|
|
455
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
456
|
+
data = global$5.extend(node.attributes.map, data);
|
|
457
|
+
}
|
|
458
|
+
if (name === 'source') {
|
|
459
|
+
if (!data.source) {
|
|
460
|
+
data.source = node.attr('src');
|
|
461
|
+
}
|
|
462
|
+
else if (!data.altsource) {
|
|
463
|
+
data.altsource = node.attr('src');
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
if (name === 'img' && !data.poster) {
|
|
467
|
+
data.poster = node.attr('src');
|
|
468
|
+
}
|
|
469
|
+
}
|
|
267
470
|
}
|
|
268
|
-
}
|
|
269
471
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
return data;
|
|
472
|
+
data.source = data.source || data.src || '';
|
|
473
|
+
data.altsource = data.altsource || '';
|
|
474
|
+
data.poster = data.poster || '';
|
|
475
|
+
return data;
|
|
275
476
|
};
|
|
276
477
|
|
|
277
|
-
const guess = url => {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
478
|
+
const guess = (url) => {
|
|
479
|
+
var _a;
|
|
480
|
+
const mimes = {
|
|
481
|
+
mp3: 'audio/mpeg',
|
|
482
|
+
m4a: 'audio/x-m4a',
|
|
483
|
+
wav: 'audio/wav',
|
|
484
|
+
mp4: 'video/mp4',
|
|
485
|
+
webm: 'video/webm',
|
|
486
|
+
ogg: 'video/ogg',
|
|
487
|
+
swf: 'application/x-shockwave-flash'
|
|
488
|
+
};
|
|
489
|
+
const fileEnd = (_a = url.toLowerCase().split('.').pop()) !== null && _a !== void 0 ? _a : '';
|
|
490
|
+
return get$1(mimes, fileEnd).getOr('');
|
|
290
491
|
};
|
|
291
492
|
|
|
292
493
|
var global$2 = tinymce.util.Tools.resolve('tinymce.html.Node');
|
|
@@ -294,924 +495,981 @@
|
|
|
294
495
|
var global$1 = tinymce.util.Tools.resolve('tinymce.html.Serializer');
|
|
295
496
|
|
|
296
497
|
const Parser = (schema, settings = {}) => global$3({
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
498
|
+
forced_root_block: false,
|
|
499
|
+
validate: false,
|
|
500
|
+
allow_conditional_comments: true,
|
|
501
|
+
...settings
|
|
301
502
|
}, schema);
|
|
302
503
|
|
|
303
504
|
const DOM = global$4.DOM;
|
|
304
|
-
const addPx = value => /^[0-9.]+$/.test(value) ? value + 'px' : value;
|
|
505
|
+
const addPx = (value) => /^[0-9.]+$/.test(value) ? (value + 'px') : value;
|
|
305
506
|
const updateEphoxEmbed = (data, node) => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
507
|
+
const style = node.attr('style');
|
|
508
|
+
const styleMap = style ? DOM.parseStyle(style) : {};
|
|
509
|
+
if (isNonNullable(data.width)) {
|
|
510
|
+
styleMap['max-width'] = addPx(data.width);
|
|
511
|
+
}
|
|
512
|
+
if (isNonNullable(data.height)) {
|
|
513
|
+
styleMap['max-height'] = addPx(data.height);
|
|
514
|
+
}
|
|
515
|
+
node.attr('style', DOM.serializeStyle(styleMap));
|
|
315
516
|
};
|
|
316
|
-
const sources = [
|
|
317
|
-
'source',
|
|
318
|
-
'altsource'
|
|
319
|
-
];
|
|
517
|
+
const sources = ['source', 'altsource'];
|
|
320
518
|
const updateHtml = (html, data, updateAll, schema) => {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
switch (name) {
|
|
334
|
-
case 'video':
|
|
335
|
-
case 'object':
|
|
336
|
-
case 'embed':
|
|
337
|
-
case 'img':
|
|
338
|
-
case 'iframe':
|
|
339
|
-
if (data.height !== undefined && data.width !== undefined) {
|
|
340
|
-
node.attr('width', data.width);
|
|
341
|
-
node.attr('height', data.height);
|
|
342
|
-
}
|
|
343
|
-
break;
|
|
344
|
-
}
|
|
345
|
-
if (updateAll) {
|
|
346
|
-
switch (name) {
|
|
347
|
-
case 'video':
|
|
348
|
-
node.attr('poster', data.poster);
|
|
349
|
-
node.attr('src', null);
|
|
350
|
-
for (let index = numSources; index < 2; index++) {
|
|
351
|
-
if (data[sources[index]]) {
|
|
352
|
-
const source = new global$2('source', 1);
|
|
353
|
-
source.attr('src', data[sources[index]]);
|
|
354
|
-
source.attr('type', data[sources[index] + 'mime'] || null);
|
|
355
|
-
node.append(source);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
break;
|
|
359
|
-
case 'iframe':
|
|
360
|
-
node.attr('src', data.source);
|
|
361
|
-
break;
|
|
362
|
-
case 'object':
|
|
363
|
-
const hasImage = node.getAll('img').length > 0;
|
|
364
|
-
if (data.poster && !hasImage) {
|
|
365
|
-
node.attr('src', data.poster);
|
|
366
|
-
const img = new global$2('img', 1);
|
|
367
|
-
img.attr('src', data.poster);
|
|
368
|
-
img.attr('width', data.width);
|
|
369
|
-
img.attr('height', data.height);
|
|
370
|
-
node.append(img);
|
|
371
|
-
}
|
|
372
|
-
break;
|
|
373
|
-
case 'source':
|
|
374
|
-
if (sourceCount < 2) {
|
|
375
|
-
node.attr('src', data[sources[sourceCount]]);
|
|
376
|
-
node.attr('type', data[sources[sourceCount] + 'mime'] || null);
|
|
377
|
-
if (!data[sources[sourceCount]]) {
|
|
378
|
-
node.remove();
|
|
379
|
-
continue;
|
|
380
|
-
}
|
|
519
|
+
let numSources = 0;
|
|
520
|
+
let sourceCount = 0;
|
|
521
|
+
const parser = Parser(schema);
|
|
522
|
+
parser.addNodeFilter('source', (nodes) => numSources = nodes.length);
|
|
523
|
+
const rootNode = parser.parse(html);
|
|
524
|
+
for (let node = rootNode; node; node = node.walk()) {
|
|
525
|
+
if (node.type === 1) {
|
|
526
|
+
const name = node.name;
|
|
527
|
+
if (node.attr('data-ephox-embed-iri')) {
|
|
528
|
+
updateEphoxEmbed(data, node);
|
|
529
|
+
// Don't continue to update if we find an EME embed
|
|
530
|
+
break;
|
|
381
531
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
532
|
+
else {
|
|
533
|
+
switch (name) {
|
|
534
|
+
case 'video':
|
|
535
|
+
case 'object':
|
|
536
|
+
case 'embed':
|
|
537
|
+
case 'img':
|
|
538
|
+
case 'iframe':
|
|
539
|
+
if (data.height !== undefined && data.width !== undefined) {
|
|
540
|
+
node.attr('width', data.width);
|
|
541
|
+
node.attr('height', data.height);
|
|
542
|
+
}
|
|
543
|
+
break;
|
|
544
|
+
}
|
|
545
|
+
if (updateAll) {
|
|
546
|
+
switch (name) {
|
|
547
|
+
case 'video':
|
|
548
|
+
node.attr('poster', data.poster);
|
|
549
|
+
node.attr('src', null);
|
|
550
|
+
// Add <source> child elements
|
|
551
|
+
for (let index = numSources; index < 2; index++) {
|
|
552
|
+
if (data[sources[index]]) {
|
|
553
|
+
const source = new global$2('source', 1);
|
|
554
|
+
source.attr('src', data[sources[index]]);
|
|
555
|
+
source.attr('type', data[sources[index] + 'mime'] || null);
|
|
556
|
+
node.append(source);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
break;
|
|
560
|
+
case 'iframe':
|
|
561
|
+
node.attr('src', data.source);
|
|
562
|
+
break;
|
|
563
|
+
case 'object':
|
|
564
|
+
const hasImage = node.getAll('img').length > 0;
|
|
565
|
+
if (data.poster && !hasImage) {
|
|
566
|
+
node.attr('src', data.poster);
|
|
567
|
+
const img = new global$2('img', 1);
|
|
568
|
+
img.attr('src', data.poster);
|
|
569
|
+
img.attr('width', data.width);
|
|
570
|
+
img.attr('height', data.height);
|
|
571
|
+
node.append(img);
|
|
572
|
+
}
|
|
573
|
+
break;
|
|
574
|
+
case 'source':
|
|
575
|
+
if (sourceCount < 2) {
|
|
576
|
+
node.attr('src', data[sources[sourceCount]]);
|
|
577
|
+
node.attr('type', data[sources[sourceCount] + 'mime'] || null);
|
|
578
|
+
if (!data[sources[sourceCount]]) {
|
|
579
|
+
node.remove();
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
sourceCount++;
|
|
584
|
+
break;
|
|
585
|
+
case 'img':
|
|
586
|
+
if (!data.poster) {
|
|
587
|
+
node.remove();
|
|
588
|
+
}
|
|
589
|
+
break;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
387
592
|
}
|
|
388
|
-
break;
|
|
389
|
-
}
|
|
390
593
|
}
|
|
391
|
-
}
|
|
392
594
|
}
|
|
393
|
-
|
|
394
|
-
return global$1({}, schema).serialize(rootNode);
|
|
595
|
+
return global$1({}, schema).serialize(rootNode);
|
|
395
596
|
};
|
|
396
597
|
|
|
397
598
|
const urlPatterns = [
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
h: 350,
|
|
459
|
-
url: 'maps.google.com/maps/ms?msid=$2&output=embed"',
|
|
460
|
-
allowFullscreen: false
|
|
461
|
-
},
|
|
462
|
-
{
|
|
463
|
-
regex: /dailymotion\.com\/video\/([^_]+)/,
|
|
464
|
-
type: 'iframe',
|
|
465
|
-
w: 480,
|
|
466
|
-
h: 270,
|
|
467
|
-
url: 'www.dailymotion.com/embed/video/$1',
|
|
468
|
-
allowFullscreen: true
|
|
469
|
-
},
|
|
470
|
-
{
|
|
471
|
-
regex: /dai\.ly\/([^_]+)/,
|
|
472
|
-
type: 'iframe',
|
|
473
|
-
w: 480,
|
|
474
|
-
h: 270,
|
|
475
|
-
url: 'www.dailymotion.com/embed/video/$1',
|
|
476
|
-
allowFullscreen: true
|
|
477
|
-
}
|
|
599
|
+
{
|
|
600
|
+
regex: /youtu\.be\/([\w\-_\?&=.]+)/i,
|
|
601
|
+
type: 'iframe', w: 560, h: 314,
|
|
602
|
+
url: 'www.youtube.com/embed/$1',
|
|
603
|
+
allowFullscreen: true
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
regex: /youtube\.com(.+)v=([^&]+)(&([a-z0-9&=\-_]+))?/i,
|
|
607
|
+
type: 'iframe', w: 560, h: 314,
|
|
608
|
+
url: 'www.youtube.com/embed/$2?$4',
|
|
609
|
+
allowFullscreen: true
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
regex: /youtube.com\/embed\/([a-z0-9\?&=\-_]+)/i,
|
|
613
|
+
type: 'iframe', w: 560, h: 314,
|
|
614
|
+
url: 'www.youtube.com/embed/$1',
|
|
615
|
+
allowFullscreen: true
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
regex: /vimeo\.com\/([0-9]+)\?h=(\w+)/,
|
|
619
|
+
type: 'iframe', w: 425, h: 350,
|
|
620
|
+
url: 'player.vimeo.com/video/$1?h=$2&title=0&byline=0&portrait=0&color=8dc7dc',
|
|
621
|
+
allowFullscreen: true
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
regex: /vimeo\.com\/(.*)\/([0-9]+)\?h=(\w+)/,
|
|
625
|
+
type: 'iframe', w: 425, h: 350,
|
|
626
|
+
url: 'player.vimeo.com/video/$2?h=$3&title=0&byline=0',
|
|
627
|
+
allowFullscreen: true
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
regex: /vimeo\.com\/([0-9]+)/,
|
|
631
|
+
type: 'iframe', w: 425, h: 350,
|
|
632
|
+
url: 'player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc',
|
|
633
|
+
allowFullscreen: true
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
regex: /vimeo\.com\/(.*)\/([0-9]+)/,
|
|
637
|
+
type: 'iframe', w: 425, h: 350,
|
|
638
|
+
url: 'player.vimeo.com/video/$2?title=0&byline=0',
|
|
639
|
+
allowFullscreen: true
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
regex: /maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,
|
|
643
|
+
type: 'iframe', w: 425, h: 350,
|
|
644
|
+
url: 'maps.google.com/maps/ms?msid=$2&output=embed"',
|
|
645
|
+
allowFullscreen: false
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
regex: /dailymotion\.com\/video\/([^_]+)/,
|
|
649
|
+
type: 'iframe', w: 480, h: 270,
|
|
650
|
+
url: 'www.dailymotion.com/embed/video/$1',
|
|
651
|
+
allowFullscreen: true
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
regex: /dai\.ly\/([^_]+)/,
|
|
655
|
+
type: 'iframe', w: 480, h: 270,
|
|
656
|
+
url: 'www.dailymotion.com/embed/video/$1',
|
|
657
|
+
allowFullscreen: true
|
|
658
|
+
}
|
|
478
659
|
];
|
|
479
|
-
const getProtocol = url => {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
660
|
+
const getProtocol = (url) => {
|
|
661
|
+
const protocolMatches = url.match(/^(https?:\/\/|www\.)(.+)$/i);
|
|
662
|
+
if (protocolMatches && protocolMatches.length > 1) {
|
|
663
|
+
return protocolMatches[1] === 'www.' ? 'https://' : protocolMatches[1];
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
return 'https://';
|
|
667
|
+
}
|
|
486
668
|
};
|
|
487
669
|
const getUrl = (pattern, url) => {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
670
|
+
const protocol = getProtocol(url);
|
|
671
|
+
const match = pattern.regex.exec(url);
|
|
672
|
+
let newUrl = protocol + pattern.url;
|
|
673
|
+
if (isNonNullable(match)) {
|
|
674
|
+
for (let i = 0; i < match.length; i++) {
|
|
675
|
+
newUrl = newUrl.replace('$' + i, () => match[i] ? match[i] : '');
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
return newUrl.replace(/\?$/, '');
|
|
497
679
|
};
|
|
498
|
-
const matchPattern = url => {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
680
|
+
const matchPattern = (url) => {
|
|
681
|
+
const patterns = urlPatterns.filter((pattern) => pattern.regex.test(url));
|
|
682
|
+
if (patterns.length > 0) {
|
|
683
|
+
return global$5.extend({}, patterns[0], { url: getUrl(patterns[0], url) });
|
|
684
|
+
}
|
|
685
|
+
else {
|
|
686
|
+
return null;
|
|
687
|
+
}
|
|
505
688
|
};
|
|
506
689
|
|
|
507
690
|
const getIframeHtml = (data, iframeTemplateCallback) => {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
691
|
+
if (iframeTemplateCallback) {
|
|
692
|
+
return iframeTemplateCallback(data);
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
const allowFullscreen = data.allowfullscreen ? ' allowFullscreen="1"' : '';
|
|
696
|
+
return '<iframe src="' + data.source + '" width="' + data.width + '" height="' + data.height + '"' + allowFullscreen + '></iframe>';
|
|
697
|
+
}
|
|
514
698
|
};
|
|
515
|
-
const getFlashHtml = data => {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
699
|
+
const getFlashHtml = (data) => {
|
|
700
|
+
let html = '<object data="' + data.source + '" width="' + data.width + '" height="' + data.height + '" type="application/x-shockwave-flash">';
|
|
701
|
+
if (data.poster) {
|
|
702
|
+
html += '<img src="' + data.poster + '" width="' + data.width + '" height="' + data.height + '" />';
|
|
703
|
+
}
|
|
704
|
+
html += '</object>';
|
|
705
|
+
return html;
|
|
522
706
|
};
|
|
523
707
|
const getAudioHtml = (data, audioTemplateCallback) => {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
708
|
+
if (audioTemplateCallback) {
|
|
709
|
+
return audioTemplateCallback(data);
|
|
710
|
+
}
|
|
711
|
+
else {
|
|
712
|
+
return ('<audio controls="controls" src="' + data.source + '">' +
|
|
713
|
+
(data.altsource ?
|
|
714
|
+
'\n<source src="' + data.altsource + '"' +
|
|
715
|
+
(data.altsourcemime ? ' type="' + data.altsourcemime + '"' : '') +
|
|
716
|
+
' />\n' : '') +
|
|
717
|
+
'</audio>');
|
|
718
|
+
}
|
|
529
719
|
};
|
|
530
720
|
const getVideoHtml = (data, videoTemplateCallback) => {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
721
|
+
if (videoTemplateCallback) {
|
|
722
|
+
return videoTemplateCallback(data);
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
return ('<video width="' + data.width +
|
|
726
|
+
'" height="' + data.height + '"' +
|
|
727
|
+
(data.poster ? ' poster="' + data.poster + '"' : '') + ' controls="controls">\n' +
|
|
728
|
+
'<source src="' + data.source + '"' +
|
|
729
|
+
(data.sourcemime ? ' type="' + data.sourcemime + '"' : '') + ' />\n' +
|
|
730
|
+
(data.altsource ? '<source src="' + data.altsource + '"' +
|
|
731
|
+
(data.altsourcemime ? ' type="' + data.altsourcemime + '"' : '') + ' />\n' : '') +
|
|
732
|
+
'</video>');
|
|
733
|
+
}
|
|
536
734
|
};
|
|
537
735
|
const dataToHtml = (editor, dataIn) => {
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
if (!data.source) {
|
|
541
|
-
global$5.extend(data, htmlToData((_a = data.embed) !== null && _a !== void 0 ? _a : '', editor.schema));
|
|
736
|
+
var _a;
|
|
737
|
+
const data = global$5.extend({}, dataIn);
|
|
542
738
|
if (!data.source) {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
739
|
+
global$5.extend(data, htmlToData((_a = data.embed) !== null && _a !== void 0 ? _a : '', editor.schema));
|
|
740
|
+
if (!data.source) {
|
|
741
|
+
return '';
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
if (!data.altsource) {
|
|
745
|
+
data.altsource = '';
|
|
746
|
+
}
|
|
747
|
+
if (!data.poster) {
|
|
748
|
+
data.poster = '';
|
|
749
|
+
}
|
|
750
|
+
data.source = editor.convertURL(data.source, 'source');
|
|
751
|
+
data.altsource = editor.convertURL(data.altsource, 'source');
|
|
752
|
+
data.sourcemime = guess(data.source);
|
|
753
|
+
data.altsourcemime = guess(data.altsource);
|
|
754
|
+
data.poster = editor.convertURL(data.poster, 'poster');
|
|
755
|
+
const pattern = matchPattern(data.source);
|
|
756
|
+
if (pattern) {
|
|
757
|
+
data.source = pattern.url;
|
|
758
|
+
data.type = pattern.type;
|
|
759
|
+
data.allowfullscreen = pattern.allowFullscreen;
|
|
760
|
+
data.width = data.width || String(pattern.w);
|
|
761
|
+
data.height = data.height || String(pattern.h);
|
|
762
|
+
}
|
|
763
|
+
if (data.embed) {
|
|
764
|
+
return updateHtml(data.embed, data, true, editor.schema);
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
const audioTemplateCallback = getAudioTemplateCallback(editor);
|
|
768
|
+
const videoTemplateCallback = getVideoTemplateCallback(editor);
|
|
769
|
+
const iframeTemplateCallback = getIframeTemplateCallback(editor);
|
|
770
|
+
data.width = data.width || '300';
|
|
771
|
+
data.height = data.height || '150';
|
|
772
|
+
global$5.each(data, (value, key) => {
|
|
773
|
+
data[key] = editor.dom.encode('' + value);
|
|
774
|
+
});
|
|
775
|
+
if (data.type === 'iframe') {
|
|
776
|
+
return getIframeHtml(data, iframeTemplateCallback);
|
|
777
|
+
}
|
|
778
|
+
else if (data.sourcemime === 'application/x-shockwave-flash') {
|
|
779
|
+
return getFlashHtml(data);
|
|
780
|
+
}
|
|
781
|
+
else if (data.sourcemime.indexOf('audio') !== -1) {
|
|
782
|
+
return getAudioHtml(data, audioTemplateCallback);
|
|
783
|
+
}
|
|
784
|
+
else {
|
|
785
|
+
return getVideoHtml(data, videoTemplateCallback);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
586
788
|
};
|
|
587
789
|
|
|
588
|
-
const isMediaElement = element => element.hasAttribute('data-mce-object') || element.hasAttribute('data-ephox-embed-iri');
|
|
589
|
-
const setup$2 = editor => {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
790
|
+
const isMediaElement = (element) => element.hasAttribute('data-mce-object') || element.hasAttribute('data-ephox-embed-iri');
|
|
791
|
+
const setup$2 = (editor) => {
|
|
792
|
+
// TINY-10774: On Safari all events bubble out even if you click on the video play button on other browsers the video element doesn't bubble the event
|
|
793
|
+
editor.on('mousedown', (e) => {
|
|
794
|
+
const previewObj = editor.dom.getParent(e.target, '.mce-preview-object');
|
|
795
|
+
if (previewObj && editor.dom.getAttrib(previewObj, 'data-mce-selected') === '2') {
|
|
796
|
+
e.stopImmediatePropagation();
|
|
797
|
+
}
|
|
798
|
+
});
|
|
799
|
+
editor.on('click keyup touchend', () => {
|
|
800
|
+
const selectedNode = editor.selection.getNode();
|
|
801
|
+
if (selectedNode && editor.dom.hasClass(selectedNode, 'mce-preview-object')) {
|
|
802
|
+
if (editor.dom.getAttrib(selectedNode, 'data-mce-selected')) {
|
|
803
|
+
selectedNode.setAttribute('data-mce-selected', '2');
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
editor.on('ObjectResized', (e) => {
|
|
808
|
+
const target = e.target;
|
|
809
|
+
if (target.getAttribute('data-mce-object')) {
|
|
810
|
+
let html = target.getAttribute('data-mce-html');
|
|
811
|
+
if (html) {
|
|
812
|
+
html = unescape(html);
|
|
813
|
+
target.setAttribute('data-mce-html', escape(updateHtml(html, {
|
|
814
|
+
width: String(e.width),
|
|
815
|
+
height: String(e.height)
|
|
816
|
+
}, false, editor.schema)));
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
});
|
|
611
820
|
};
|
|
612
821
|
|
|
613
822
|
const cache = {};
|
|
614
823
|
const embedPromise = (data, dataToHtml, handler) => {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
824
|
+
return new Promise((res, rej) => {
|
|
825
|
+
const wrappedResolve = (response) => {
|
|
826
|
+
if (response.html) {
|
|
827
|
+
cache[data.source] = response;
|
|
828
|
+
}
|
|
829
|
+
return res({
|
|
830
|
+
url: data.source,
|
|
831
|
+
html: response.html ? response.html : dataToHtml(data)
|
|
832
|
+
});
|
|
833
|
+
};
|
|
834
|
+
if (cache[data.source]) {
|
|
835
|
+
wrappedResolve(cache[data.source]);
|
|
836
|
+
}
|
|
837
|
+
else {
|
|
838
|
+
handler({ url: data.source }).then(wrappedResolve).catch(rej);
|
|
839
|
+
}
|
|
840
|
+
});
|
|
631
841
|
};
|
|
632
|
-
const defaultPromise = (data, dataToHtml) => Promise.resolve({
|
|
633
|
-
|
|
634
|
-
url: data.source
|
|
635
|
-
});
|
|
636
|
-
const loadedData = editor => data => dataToHtml(editor, data);
|
|
842
|
+
const defaultPromise = (data, dataToHtml) => Promise.resolve({ html: dataToHtml(data), url: data.source });
|
|
843
|
+
const loadedData = (editor) => (data) => dataToHtml(editor, data);
|
|
637
844
|
const getEmbedHtml = (editor, data) => {
|
|
638
|
-
|
|
639
|
-
|
|
845
|
+
const embedHandler = getUrlResolver(editor);
|
|
846
|
+
return embedHandler ? embedPromise(data, loadedData(editor), embedHandler) : defaultPromise(data, loadedData(editor));
|
|
640
847
|
};
|
|
641
|
-
const isCached = url => has(cache, url);
|
|
848
|
+
const isCached = (url) => has(cache, url);
|
|
642
849
|
|
|
643
|
-
const extractMeta = (sourceInput, data) => get$1(data, sourceInput).bind(mainData => get$1(mainData, 'meta'));
|
|
644
|
-
const getValue = (data, metaData, sourceInput) => prop => {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
850
|
+
const extractMeta = (sourceInput, data) => get$1(data, sourceInput).bind((mainData) => get$1(mainData, 'meta'));
|
|
851
|
+
const getValue = (data, metaData, sourceInput) => (prop) => {
|
|
852
|
+
// Cases:
|
|
853
|
+
// 1. Get the nested value prop (component is the executed urlinput)
|
|
854
|
+
// 2. Get from metadata (a urlinput was executed but urlinput != this component)
|
|
855
|
+
// 3. Not a urlinput so just get string
|
|
856
|
+
// If prop === sourceInput do 1, 2 then 3, else do 2 then 1 or 3
|
|
857
|
+
// ASSUMPTION: we only want to get values for props that already exist in data
|
|
858
|
+
const getFromData = () => get$1(data, prop);
|
|
859
|
+
const getFromMetaData = () => get$1(metaData, prop);
|
|
860
|
+
const getNonEmptyValue = (c) => get$1(c, 'value').bind((v) => v.length > 0 ? Optional.some(v) : Optional.none());
|
|
861
|
+
const getFromValueFirst = () => getFromData().bind((child) => isObject(child)
|
|
862
|
+
? getNonEmptyValue(child).orThunk(getFromMetaData)
|
|
863
|
+
: getFromMetaData().orThunk(() => Optional.from(child)));
|
|
864
|
+
const getFromMetaFirst = () => getFromMetaData().orThunk(() => getFromData().bind((child) => isObject(child)
|
|
865
|
+
? getNonEmptyValue(child)
|
|
866
|
+
: Optional.from(child)));
|
|
867
|
+
return { [prop]: (prop === sourceInput ? getFromValueFirst() : getFromMetaFirst()).getOr('') };
|
|
651
868
|
};
|
|
652
869
|
const getDimensions = (data, metaData) => {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
], prop => {
|
|
659
|
-
get$1(metaData, prop).orThunk(() => get$1(dims, prop)).each(value => dimensions[prop] = value);
|
|
870
|
+
const dimensions = {};
|
|
871
|
+
get$1(data, 'dimensions').each((dims) => {
|
|
872
|
+
each$1(['width', 'height'], (prop) => {
|
|
873
|
+
get$1(metaData, prop).orThunk(() => get$1(dims, prop)).each((value) => dimensions[prop] = value);
|
|
874
|
+
});
|
|
660
875
|
});
|
|
661
|
-
|
|
662
|
-
return dimensions;
|
|
876
|
+
return dimensions;
|
|
663
877
|
};
|
|
664
878
|
const unwrap = (data, sourceInput) => {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
879
|
+
const metaData = sourceInput && sourceInput !== 'dimensions' ? extractMeta(sourceInput, data).getOr({}) : {};
|
|
880
|
+
const get = getValue(data, metaData, sourceInput);
|
|
881
|
+
return {
|
|
882
|
+
...get('source'),
|
|
883
|
+
...get('altsource'),
|
|
884
|
+
...get('poster'),
|
|
885
|
+
...get('embed'),
|
|
886
|
+
...getDimensions(data, metaData)
|
|
887
|
+
};
|
|
674
888
|
};
|
|
675
|
-
const wrap = data => {
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
'width',
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
wrapped.dimensions = dimensions;
|
|
889
|
+
const wrap = (data) => {
|
|
890
|
+
const wrapped = {
|
|
891
|
+
...data,
|
|
892
|
+
source: { value: get$1(data, 'source').getOr('') },
|
|
893
|
+
altsource: { value: get$1(data, 'altsource').getOr('') },
|
|
894
|
+
poster: { value: get$1(data, 'poster').getOr('') }
|
|
895
|
+
};
|
|
896
|
+
// Add additional size values that may or may not have been in the html
|
|
897
|
+
each$1(['width', 'height'], (prop) => {
|
|
898
|
+
get$1(data, prop).each((value) => {
|
|
899
|
+
const dimensions = wrapped.dimensions || {};
|
|
900
|
+
dimensions[prop] = value;
|
|
901
|
+
wrapped.dimensions = dimensions;
|
|
902
|
+
});
|
|
690
903
|
});
|
|
691
|
-
|
|
692
|
-
return wrapped;
|
|
693
|
-
};
|
|
694
|
-
const handleError = editor => error => {
|
|
695
|
-
const errorMessage = error && error.msg ? 'Media embed handler error: ' + error.msg : 'Media embed handler threw unknown error.';
|
|
696
|
-
editor.notificationManager.open({
|
|
697
|
-
type: 'error',
|
|
698
|
-
text: errorMessage
|
|
699
|
-
});
|
|
904
|
+
return wrapped;
|
|
700
905
|
};
|
|
701
|
-
const
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
if (isEmbedIframe(data.source, data.type)) {
|
|
707
|
-
const rect = editor.dom.getRect(element);
|
|
708
|
-
return {
|
|
709
|
-
width: rect.w.toString().replace(/px$/, ''),
|
|
710
|
-
height: rect.h.toString().replace(/px$/, '')
|
|
711
|
-
};
|
|
712
|
-
} else {
|
|
713
|
-
return {};
|
|
714
|
-
}
|
|
715
|
-
};
|
|
716
|
-
const dimensions = getDimensionsOfElement();
|
|
717
|
-
return {
|
|
718
|
-
embed: snippet,
|
|
719
|
-
...data,
|
|
720
|
-
...dimensions
|
|
721
|
-
};
|
|
906
|
+
const handleError = (editor) => (error) => {
|
|
907
|
+
const errorMessage = error && error.msg ?
|
|
908
|
+
'Media embed handler error: ' + error.msg :
|
|
909
|
+
'Media embed handler threw unknown error.';
|
|
910
|
+
editor.notificationManager.open({ type: 'error', text: errorMessage });
|
|
722
911
|
};
|
|
723
|
-
const
|
|
724
|
-
|
|
725
|
-
const
|
|
726
|
-
const
|
|
727
|
-
const
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
912
|
+
const getEditorData = (editor) => {
|
|
913
|
+
const element = editor.selection.getNode();
|
|
914
|
+
const snippet = isMediaElement(element) ? editor.serializer.serialize(element, { selection: true }) : '';
|
|
915
|
+
const data = htmlToData(snippet, editor.schema);
|
|
916
|
+
const getDimensionsOfElement = () => {
|
|
917
|
+
if (isEmbedIframe(data.source, data.type)) {
|
|
918
|
+
const rect = editor.dom.getRect(element);
|
|
919
|
+
return {
|
|
920
|
+
width: rect.w.toString().replace(/px$/, ''),
|
|
921
|
+
height: rect.h.toString().replace(/px$/, ''),
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
else {
|
|
925
|
+
return {};
|
|
926
|
+
}
|
|
731
927
|
};
|
|
732
|
-
|
|
733
|
-
|
|
928
|
+
const dimensions = getDimensionsOfElement();
|
|
929
|
+
return {
|
|
930
|
+
embed: snippet,
|
|
931
|
+
...data,
|
|
932
|
+
...dimensions
|
|
933
|
+
};
|
|
934
|
+
};
|
|
935
|
+
const addEmbedHtml = (api, editor) => (response) => {
|
|
936
|
+
// Only set values if a URL has been defined
|
|
937
|
+
if (isString(response.url) && response.url.trim().length > 0) {
|
|
938
|
+
const html = response.html;
|
|
939
|
+
const snippetData = htmlToData(html, editor.schema);
|
|
940
|
+
const nuData = {
|
|
941
|
+
...snippetData,
|
|
942
|
+
source: response.url,
|
|
943
|
+
embed: html
|
|
944
|
+
};
|
|
945
|
+
api.setData(wrap(nuData));
|
|
946
|
+
}
|
|
734
947
|
};
|
|
735
948
|
const selectPlaceholder = (editor, beforeObjects) => {
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
for (let
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
949
|
+
const afterObjects = editor.dom.select('*[data-mce-object]');
|
|
950
|
+
// Find new image placeholder so we can select it
|
|
951
|
+
for (let i = 0; i < beforeObjects.length; i++) {
|
|
952
|
+
for (let y = afterObjects.length - 1; y >= 0; y--) {
|
|
953
|
+
if (beforeObjects[i] === afterObjects[y]) {
|
|
954
|
+
afterObjects.splice(y, 1);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
editor.selection.select(afterObjects[0]);
|
|
745
959
|
};
|
|
746
960
|
const handleInsert = (editor, html) => {
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
961
|
+
const beforeObjects = editor.dom.select('*[data-mce-object]');
|
|
962
|
+
editor.insertContent(html);
|
|
963
|
+
selectPlaceholder(editor, beforeObjects);
|
|
964
|
+
editor.nodeChanged();
|
|
751
965
|
};
|
|
752
966
|
const isEmbedIframe = (url, mediaDataType) => isNonNullable(mediaDataType) && mediaDataType === 'ephox-embed-iri' && isNonNullable(matchPattern(url));
|
|
753
967
|
const shouldInsertAsNewIframe = (prevData, newData) => {
|
|
754
|
-
|
|
755
|
-
|
|
968
|
+
const hasDimensionsChanged = (prevData, newData) => prevData.width !== newData.width || prevData.height !== newData.height;
|
|
969
|
+
return hasDimensionsChanged(prevData, newData) && isEmbedIframe(newData.source, prevData.type);
|
|
756
970
|
};
|
|
757
971
|
const submitForm = (prevData, newData, editor) => {
|
|
758
|
-
var _a;
|
|
759
|
-
newData.embed = shouldInsertAsNewIframe(prevData, newData) && hasDimensions(editor) ? dataToHtml(editor, {
|
|
760
|
-
...newData,
|
|
761
|
-
embed: ''
|
|
762
|
-
}) : updateHtml((_a = newData.embed) !== null && _a !== void 0 ? _a : '', newData, false, editor.schema);
|
|
763
|
-
if (newData.embed && (prevData.source === newData.source || isCached(newData.source))) {
|
|
764
|
-
handleInsert(editor, newData.embed);
|
|
765
|
-
} else {
|
|
766
|
-
getEmbedHtml(editor, newData).then(response => {
|
|
767
|
-
handleInsert(editor, response.html);
|
|
768
|
-
}).catch(handleError(editor));
|
|
769
|
-
}
|
|
770
|
-
};
|
|
771
|
-
const showDialog = editor => {
|
|
772
|
-
const editorData = getEditorData(editor);
|
|
773
|
-
const currentData = Cell(editorData);
|
|
774
|
-
const initialData = wrap(editorData);
|
|
775
|
-
const handleSource = (prevData, api) => {
|
|
776
|
-
const serviceData = unwrap(api.getData(), 'source');
|
|
777
|
-
if (prevData.source !== serviceData.source) {
|
|
778
|
-
addEmbedHtml(win, editor)({
|
|
779
|
-
url: serviceData.source,
|
|
780
|
-
html: ''
|
|
781
|
-
});
|
|
782
|
-
getEmbedHtml(editor, serviceData).then(addEmbedHtml(win, editor)).catch(handleError(editor));
|
|
783
|
-
}
|
|
784
|
-
};
|
|
785
|
-
const handleEmbed = api => {
|
|
786
972
|
var _a;
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
}));
|
|
802
|
-
};
|
|
803
|
-
const mediaInput = [{
|
|
804
|
-
name: 'source',
|
|
805
|
-
type: 'urlinput',
|
|
806
|
-
filetype: 'media',
|
|
807
|
-
label: 'Source',
|
|
808
|
-
picker_text: 'Browse files'
|
|
809
|
-
}];
|
|
810
|
-
const sizeInput = !hasDimensions(editor) ? [] : [{
|
|
811
|
-
type: 'sizeinput',
|
|
812
|
-
name: 'dimensions',
|
|
813
|
-
label: 'Constrain proportions',
|
|
814
|
-
constrain: true
|
|
815
|
-
}];
|
|
816
|
-
const generalTab = {
|
|
817
|
-
title: 'General',
|
|
818
|
-
name: 'general',
|
|
819
|
-
items: flatten([
|
|
820
|
-
mediaInput,
|
|
821
|
-
sizeInput
|
|
822
|
-
])
|
|
823
|
-
};
|
|
824
|
-
const embedTextarea = {
|
|
825
|
-
type: 'textarea',
|
|
826
|
-
name: 'embed',
|
|
827
|
-
label: 'Paste your embed code below:'
|
|
828
|
-
};
|
|
829
|
-
const embedTab = {
|
|
830
|
-
title: 'Embed',
|
|
831
|
-
items: [embedTextarea]
|
|
832
|
-
};
|
|
833
|
-
const advancedFormItems = [];
|
|
834
|
-
if (hasAltSource(editor)) {
|
|
835
|
-
advancedFormItems.push({
|
|
836
|
-
name: 'altsource',
|
|
837
|
-
type: 'urlinput',
|
|
838
|
-
filetype: 'media',
|
|
839
|
-
label: 'Alternative source URL'
|
|
840
|
-
});
|
|
841
|
-
}
|
|
842
|
-
if (hasPoster(editor)) {
|
|
843
|
-
advancedFormItems.push({
|
|
844
|
-
name: 'poster',
|
|
845
|
-
type: 'urlinput',
|
|
846
|
-
filetype: 'image',
|
|
847
|
-
label: 'Media poster (Image URL)'
|
|
848
|
-
});
|
|
849
|
-
}
|
|
850
|
-
const advancedTab = {
|
|
851
|
-
title: 'Advanced',
|
|
852
|
-
name: 'advanced',
|
|
853
|
-
items: advancedFormItems
|
|
854
|
-
};
|
|
855
|
-
const tabs = [
|
|
856
|
-
generalTab,
|
|
857
|
-
embedTab
|
|
858
|
-
];
|
|
859
|
-
if (advancedFormItems.length > 0) {
|
|
860
|
-
tabs.push(advancedTab);
|
|
861
|
-
}
|
|
862
|
-
const body = {
|
|
863
|
-
type: 'tabpanel',
|
|
864
|
-
tabs
|
|
865
|
-
};
|
|
866
|
-
const win = editor.windowManager.open({
|
|
867
|
-
title: 'Insert/Edit Media',
|
|
868
|
-
size: 'normal',
|
|
869
|
-
body,
|
|
870
|
-
buttons: [
|
|
871
|
-
{
|
|
872
|
-
type: 'cancel',
|
|
873
|
-
name: 'cancel',
|
|
874
|
-
text: 'Cancel'
|
|
875
|
-
},
|
|
876
|
-
{
|
|
877
|
-
type: 'submit',
|
|
878
|
-
name: 'save',
|
|
879
|
-
text: 'Save',
|
|
880
|
-
primary: true
|
|
881
|
-
}
|
|
882
|
-
],
|
|
883
|
-
onSubmit: api => {
|
|
884
|
-
const serviceData = unwrap(api.getData());
|
|
885
|
-
submitForm(currentData.get(), serviceData, editor);
|
|
886
|
-
api.close();
|
|
887
|
-
},
|
|
888
|
-
onChange: (api, detail) => {
|
|
889
|
-
switch (detail.name) {
|
|
890
|
-
case 'source':
|
|
891
|
-
handleSource(currentData.get(), api);
|
|
892
|
-
break;
|
|
893
|
-
case 'embed':
|
|
894
|
-
handleEmbed(api);
|
|
895
|
-
break;
|
|
896
|
-
case 'dimensions':
|
|
897
|
-
case 'altsource':
|
|
898
|
-
case 'poster':
|
|
899
|
-
handleUpdate(api, detail.name, currentData.get());
|
|
900
|
-
break;
|
|
901
|
-
}
|
|
902
|
-
currentData.set(unwrap(api.getData()));
|
|
903
|
-
},
|
|
904
|
-
initialData
|
|
905
|
-
});
|
|
973
|
+
newData.embed =
|
|
974
|
+
shouldInsertAsNewIframe(prevData, newData) && hasDimensions(editor)
|
|
975
|
+
? dataToHtml(editor, { ...newData, embed: '' })
|
|
976
|
+
: updateHtml((_a = newData.embed) !== null && _a !== void 0 ? _a : '', newData, false, editor.schema);
|
|
977
|
+
// Only fetch the embed HTML content if the URL has changed from what it previously was
|
|
978
|
+
if (newData.embed && (prevData.source === newData.source || isCached(newData.source))) {
|
|
979
|
+
handleInsert(editor, newData.embed);
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
getEmbedHtml(editor, newData)
|
|
983
|
+
.then((response) => {
|
|
984
|
+
handleInsert(editor, response.html);
|
|
985
|
+
}).catch(handleError(editor));
|
|
986
|
+
}
|
|
906
987
|
};
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
988
|
+
const showDialog = (editor) => {
|
|
989
|
+
const editorData = getEditorData(editor);
|
|
990
|
+
const currentData = Cell(editorData);
|
|
991
|
+
const initialData = wrap(editorData);
|
|
992
|
+
const handleSource = (prevData, api) => {
|
|
993
|
+
const serviceData = unwrap(api.getData(), 'source');
|
|
994
|
+
// If a new URL is entered, then clear the embed html and fetch the new data
|
|
995
|
+
if (prevData.source !== serviceData.source) {
|
|
996
|
+
addEmbedHtml(win, editor)({ url: serviceData.source, html: '' });
|
|
997
|
+
getEmbedHtml(editor, serviceData)
|
|
998
|
+
.then(addEmbedHtml(win, editor))
|
|
999
|
+
.catch(handleError(editor));
|
|
1000
|
+
}
|
|
1001
|
+
};
|
|
1002
|
+
const handleEmbed = (api) => {
|
|
1003
|
+
var _a;
|
|
1004
|
+
const data = unwrap(api.getData());
|
|
1005
|
+
const dataFromEmbed = htmlToData((_a = data.embed) !== null && _a !== void 0 ? _a : '', editor.schema);
|
|
1006
|
+
api.setData(wrap(dataFromEmbed));
|
|
1007
|
+
};
|
|
1008
|
+
const handleUpdate = (api, sourceInput, prevData) => {
|
|
1009
|
+
const dialogData = unwrap(api.getData(), sourceInput);
|
|
1010
|
+
const data = shouldInsertAsNewIframe(prevData, dialogData) && hasDimensions(editor)
|
|
1011
|
+
? { ...dialogData, embed: '' }
|
|
1012
|
+
: dialogData;
|
|
1013
|
+
const embed = dataToHtml(editor, data);
|
|
1014
|
+
api.setData(wrap({
|
|
1015
|
+
...data,
|
|
1016
|
+
embed
|
|
1017
|
+
}));
|
|
1018
|
+
};
|
|
1019
|
+
const mediaInput = [{
|
|
1020
|
+
name: 'source',
|
|
1021
|
+
type: 'urlinput',
|
|
1022
|
+
filetype: 'media',
|
|
1023
|
+
label: 'Source',
|
|
1024
|
+
picker_text: 'Browse files'
|
|
1025
|
+
}];
|
|
1026
|
+
const sizeInput = !hasDimensions(editor) ? [] : [{
|
|
1027
|
+
type: 'sizeinput',
|
|
1028
|
+
name: 'dimensions',
|
|
1029
|
+
label: 'Constrain proportions',
|
|
1030
|
+
constrain: true
|
|
1031
|
+
}];
|
|
1032
|
+
const generalTab = {
|
|
1033
|
+
title: 'General',
|
|
1034
|
+
name: 'general',
|
|
1035
|
+
items: flatten([mediaInput, sizeInput])
|
|
1036
|
+
};
|
|
1037
|
+
const embedTextarea = {
|
|
1038
|
+
type: 'textarea',
|
|
1039
|
+
name: 'embed',
|
|
1040
|
+
label: 'Paste your embed code below:'
|
|
1041
|
+
};
|
|
1042
|
+
const embedTab = {
|
|
1043
|
+
title: 'Embed',
|
|
1044
|
+
items: [
|
|
1045
|
+
embedTextarea
|
|
1046
|
+
]
|
|
1047
|
+
};
|
|
1048
|
+
const advancedFormItems = [];
|
|
1049
|
+
if (hasAltSource(editor)) {
|
|
1050
|
+
advancedFormItems.push({
|
|
1051
|
+
name: 'altsource',
|
|
1052
|
+
type: 'urlinput',
|
|
1053
|
+
filetype: 'media',
|
|
1054
|
+
label: 'Alternative source URL'
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
if (hasPoster(editor)) {
|
|
1058
|
+
advancedFormItems.push({
|
|
1059
|
+
name: 'poster',
|
|
1060
|
+
type: 'urlinput',
|
|
1061
|
+
filetype: 'image',
|
|
1062
|
+
label: 'Media poster (Image URL)'
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
const advancedTab = {
|
|
1066
|
+
title: 'Advanced',
|
|
1067
|
+
name: 'advanced',
|
|
1068
|
+
items: advancedFormItems
|
|
1069
|
+
};
|
|
1070
|
+
const tabs = [
|
|
1071
|
+
generalTab,
|
|
1072
|
+
embedTab
|
|
1073
|
+
];
|
|
1074
|
+
if (advancedFormItems.length > 0) {
|
|
1075
|
+
tabs.push(advancedTab);
|
|
1076
|
+
}
|
|
1077
|
+
const body = {
|
|
1078
|
+
type: 'tabpanel',
|
|
1079
|
+
tabs
|
|
1080
|
+
};
|
|
1081
|
+
const win = editor.windowManager.open({
|
|
1082
|
+
title: 'Insert/Edit Media',
|
|
1083
|
+
size: 'normal',
|
|
1084
|
+
body,
|
|
1085
|
+
buttons: [
|
|
1086
|
+
{
|
|
1087
|
+
type: 'cancel',
|
|
1088
|
+
name: 'cancel',
|
|
1089
|
+
text: 'Cancel'
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
type: 'submit',
|
|
1093
|
+
name: 'save',
|
|
1094
|
+
text: 'Save',
|
|
1095
|
+
primary: true
|
|
1096
|
+
}
|
|
1097
|
+
],
|
|
1098
|
+
onSubmit: (api) => {
|
|
1099
|
+
const serviceData = unwrap(api.getData());
|
|
1100
|
+
submitForm(currentData.get(), serviceData, editor);
|
|
1101
|
+
api.close();
|
|
1102
|
+
},
|
|
1103
|
+
onChange: (api, detail) => {
|
|
1104
|
+
switch (detail.name) {
|
|
1105
|
+
case 'source':
|
|
1106
|
+
handleSource(currentData.get(), api);
|
|
1107
|
+
break;
|
|
1108
|
+
case 'embed':
|
|
1109
|
+
handleEmbed(api);
|
|
1110
|
+
break;
|
|
1111
|
+
case 'dimensions':
|
|
1112
|
+
case 'altsource':
|
|
1113
|
+
case 'poster':
|
|
1114
|
+
handleUpdate(api, detail.name, currentData.get());
|
|
1115
|
+
break;
|
|
1116
|
+
}
|
|
1117
|
+
currentData.set(unwrap(api.getData()));
|
|
1118
|
+
},
|
|
1119
|
+
initialData
|
|
1120
|
+
});
|
|
913
1121
|
};
|
|
914
1122
|
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
1123
|
+
const get = (editor) => {
|
|
1124
|
+
const showDialog$1 = () => {
|
|
1125
|
+
showDialog(editor);
|
|
1126
|
+
};
|
|
1127
|
+
return {
|
|
1128
|
+
showDialog: showDialog$1
|
|
1129
|
+
};
|
|
920
1130
|
};
|
|
921
1131
|
|
|
922
|
-
const
|
|
923
|
-
|
|
924
|
-
|
|
1132
|
+
const register$1 = (editor) => {
|
|
1133
|
+
const showDialog$1 = () => {
|
|
1134
|
+
showDialog(editor);
|
|
1135
|
+
};
|
|
1136
|
+
editor.addCommand('mceMedia', showDialog$1);
|
|
925
1137
|
};
|
|
926
1138
|
|
|
927
1139
|
var global = tinymce.util.Tools.resolve('tinymce.Env');
|
|
928
1140
|
|
|
929
|
-
const isLiveEmbedNode = node => {
|
|
930
|
-
|
|
931
|
-
|
|
1141
|
+
const isLiveEmbedNode = (node) => {
|
|
1142
|
+
const name = node.name;
|
|
1143
|
+
return name === 'iframe' || name === 'video' || name === 'audio';
|
|
932
1144
|
};
|
|
933
1145
|
const getDimension = (node, styles, dimension, defaultValue = null) => {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1146
|
+
const value = node.attr(dimension);
|
|
1147
|
+
if (isNonNullable(value)) {
|
|
1148
|
+
return value;
|
|
1149
|
+
}
|
|
1150
|
+
else if (!has(styles, dimension)) {
|
|
1151
|
+
return defaultValue;
|
|
1152
|
+
}
|
|
1153
|
+
else {
|
|
1154
|
+
return null;
|
|
1155
|
+
}
|
|
942
1156
|
};
|
|
943
1157
|
const setDimensions = (node, previewNode, styles) => {
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
1158
|
+
// Apply dimensions for video elements to maintain legacy behaviour
|
|
1159
|
+
const useDefaults = previewNode.name === 'img' || node.name === 'video';
|
|
1160
|
+
// Determine the defaults
|
|
1161
|
+
const defaultWidth = useDefaults ? '300' : null;
|
|
1162
|
+
const fallbackHeight = node.name === 'audio' ? '30' : '150';
|
|
1163
|
+
const defaultHeight = useDefaults ? fallbackHeight : null;
|
|
1164
|
+
previewNode.attr({
|
|
1165
|
+
width: getDimension(node, styles, 'width', defaultWidth),
|
|
1166
|
+
height: getDimension(node, styles, 'height', defaultHeight)
|
|
1167
|
+
});
|
|
952
1168
|
};
|
|
953
1169
|
const appendNodeContent = (editor, nodeName, previewNode, html) => {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1170
|
+
const newNode = Parser(editor.schema).parse(html, { context: nodeName });
|
|
1171
|
+
while (newNode.firstChild) {
|
|
1172
|
+
previewNode.append(newNode.firstChild);
|
|
1173
|
+
}
|
|
958
1174
|
};
|
|
959
1175
|
const createPlaceholderNode = (editor, node) => {
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1176
|
+
const name = node.name;
|
|
1177
|
+
const placeHolder = new global$2('img', 1);
|
|
1178
|
+
retainAttributesAndInnerHtml(editor, node, placeHolder);
|
|
1179
|
+
setDimensions(node, placeHolder, {});
|
|
1180
|
+
placeHolder.attr({
|
|
1181
|
+
'style': node.attr('style'),
|
|
1182
|
+
'src': global.transparentSrc,
|
|
1183
|
+
'data-mce-object': name,
|
|
1184
|
+
'class': 'mce-object mce-object-' + name
|
|
1185
|
+
});
|
|
1186
|
+
return placeHolder;
|
|
971
1187
|
};
|
|
972
1188
|
const createPreviewNode = (editor, node) => {
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
});
|
|
982
|
-
retainAttributesAndInnerHtml(editor, node, previewWrapper);
|
|
983
|
-
const styles = editor.dom.parseStyle((_a = node.attr('style')) !== null && _a !== void 0 ? _a : '');
|
|
984
|
-
const previewNode = new global$2(name, 1);
|
|
985
|
-
setDimensions(node, previewNode, styles);
|
|
986
|
-
previewNode.attr({
|
|
987
|
-
src: node.attr('src'),
|
|
988
|
-
style: node.attr('style'),
|
|
989
|
-
class: node.attr('class')
|
|
990
|
-
});
|
|
991
|
-
if (name === 'iframe') {
|
|
992
|
-
previewNode.attr({
|
|
993
|
-
allowfullscreen: node.attr('allowfullscreen'),
|
|
994
|
-
frameborder: '0',
|
|
995
|
-
sandbox: node.attr('sandbox')
|
|
1189
|
+
var _a;
|
|
1190
|
+
const name = node.name;
|
|
1191
|
+
const previewWrapper = new global$2('span', 1);
|
|
1192
|
+
previewWrapper.attr({
|
|
1193
|
+
'contentEditable': 'false',
|
|
1194
|
+
'style': node.attr('style'),
|
|
1195
|
+
'data-mce-object': name,
|
|
1196
|
+
'class': 'mce-preview-object mce-object-' + name
|
|
996
1197
|
});
|
|
997
|
-
|
|
998
|
-
const
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
'preload'
|
|
1006
|
-
];
|
|
1007
|
-
each$1(attrs, attrName => {
|
|
1008
|
-
previewNode.attr(attrName, node.attr(attrName));
|
|
1198
|
+
retainAttributesAndInnerHtml(editor, node, previewWrapper);
|
|
1199
|
+
const styles = editor.dom.parseStyle((_a = node.attr('style')) !== null && _a !== void 0 ? _a : '');
|
|
1200
|
+
const previewNode = new global$2(name, 1);
|
|
1201
|
+
setDimensions(node, previewNode, styles);
|
|
1202
|
+
previewNode.attr({
|
|
1203
|
+
src: node.attr('src'),
|
|
1204
|
+
style: node.attr('style'),
|
|
1205
|
+
class: node.attr('class')
|
|
1009
1206
|
});
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1207
|
+
if (name === 'iframe') {
|
|
1208
|
+
previewNode.attr({
|
|
1209
|
+
allowfullscreen: node.attr('allowfullscreen'),
|
|
1210
|
+
frameborder: '0',
|
|
1211
|
+
sandbox: node.attr('sandbox'),
|
|
1212
|
+
referrerpolicy: node.attr('referrerpolicy')
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
else {
|
|
1216
|
+
// Exclude autoplay as we don't want video/audio to play by default
|
|
1217
|
+
const attrs = ['controls', 'crossorigin', 'currentTime', 'loop', 'muted', 'poster', 'preload'];
|
|
1218
|
+
each$1(attrs, (attrName) => {
|
|
1219
|
+
previewNode.attr(attrName, node.attr(attrName));
|
|
1220
|
+
});
|
|
1221
|
+
// Recreate the child nodes using the sanitized inner HTML
|
|
1222
|
+
const sanitizedHtml = previewWrapper.attr('data-mce-html');
|
|
1223
|
+
if (isNonNullable(sanitizedHtml)) {
|
|
1224
|
+
appendNodeContent(editor, name, previewNode, unescape(sanitizedHtml));
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
const shimNode = new global$2('span', 1);
|
|
1228
|
+
shimNode.attr('class', 'mce-shim');
|
|
1229
|
+
previewWrapper.append(previewNode);
|
|
1230
|
+
previewWrapper.append(shimNode);
|
|
1231
|
+
return previewWrapper;
|
|
1020
1232
|
};
|
|
1021
1233
|
const retainAttributesAndInnerHtml = (editor, sourceNode, targetNode) => {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1234
|
+
var _a;
|
|
1235
|
+
// Prefix all attributes except internal (data-mce-*), width, height and style since we
|
|
1236
|
+
// will add these to the placeholder
|
|
1237
|
+
const attribs = (_a = sourceNode.attributes) !== null && _a !== void 0 ? _a : [];
|
|
1238
|
+
let ai = attribs.length;
|
|
1239
|
+
while (ai--) {
|
|
1240
|
+
const attrName = attribs[ai].name;
|
|
1241
|
+
let attrValue = attribs[ai].value;
|
|
1242
|
+
if (attrName !== 'width' && attrName !== 'height' && attrName !== 'style' && !startsWith(attrName, 'data-mce-')) {
|
|
1243
|
+
if (attrName === 'data' || attrName === 'src') {
|
|
1244
|
+
attrValue = editor.convertURL(attrValue, attrName);
|
|
1245
|
+
}
|
|
1246
|
+
targetNode.attr('data-mce-p-' + attrName, attrValue);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
// Place the inner HTML contents inside an escaped attribute
|
|
1250
|
+
// This enables us to copy/paste the fake object
|
|
1251
|
+
const serializer = global$1({ inner: true }, editor.schema);
|
|
1252
|
+
const tempNode = new global$2('div', 1);
|
|
1253
|
+
each$1(sourceNode.children(), (child) => tempNode.append(child));
|
|
1254
|
+
const innerHtml = serializer.serialize(tempNode);
|
|
1255
|
+
if (innerHtml) {
|
|
1256
|
+
targetNode.attr('data-mce-html', escape(innerHtml));
|
|
1257
|
+
targetNode.empty();
|
|
1258
|
+
}
|
|
1043
1259
|
};
|
|
1044
|
-
const isPageEmbedWrapper = node => {
|
|
1045
|
-
|
|
1046
|
-
|
|
1260
|
+
const isPageEmbedWrapper = (node) => {
|
|
1261
|
+
const nodeClass = node.attr('class');
|
|
1262
|
+
return isString(nodeClass) && /\btiny-pageembed\b/.test(nodeClass);
|
|
1047
1263
|
};
|
|
1048
|
-
const isWithinEmbedWrapper = node => {
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1264
|
+
const isWithinEmbedWrapper = (node) => {
|
|
1265
|
+
let tempNode = node;
|
|
1266
|
+
while ((tempNode = tempNode.parent)) {
|
|
1267
|
+
if (tempNode.attr('data-ephox-embed-iri') || isPageEmbedWrapper(tempNode)) {
|
|
1268
|
+
return true;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
return false;
|
|
1056
1272
|
};
|
|
1057
|
-
const placeHolderConverter = editor => nodes => {
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1273
|
+
const placeHolderConverter = (editor) => (nodes) => {
|
|
1274
|
+
let i = nodes.length;
|
|
1275
|
+
let node;
|
|
1276
|
+
while (i--) {
|
|
1277
|
+
node = nodes[i];
|
|
1278
|
+
if (!node.parent) {
|
|
1279
|
+
continue;
|
|
1280
|
+
}
|
|
1281
|
+
if (node.parent.attr('data-mce-object')) {
|
|
1282
|
+
continue;
|
|
1283
|
+
}
|
|
1284
|
+
if (isLiveEmbedNode(node) && hasLiveEmbeds(editor)) {
|
|
1285
|
+
if (!isWithinEmbedWrapper(node)) {
|
|
1286
|
+
node.replace(createPreviewNode(editor, node));
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
else {
|
|
1290
|
+
if (!isWithinEmbedWrapper(node)) {
|
|
1291
|
+
node.replace(createPlaceholderNode(editor, node));
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1078
1295
|
};
|
|
1079
1296
|
|
|
1080
|
-
const parseAndSanitize = (editor,
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
sanitize,
|
|
1086
|
-
validate
|
|
1087
|
-
}).parse(html, { context });
|
|
1297
|
+
const parseAndSanitize = (editor, html) => {
|
|
1298
|
+
const getEditorOption = editor.options.get;
|
|
1299
|
+
const sanitize = getEditorOption('xss_sanitization');
|
|
1300
|
+
const validate = shouldFilterHtml(editor);
|
|
1301
|
+
return Parser(editor.schema, { sanitize, validate }).parse(html);
|
|
1088
1302
|
};
|
|
1089
1303
|
|
|
1090
|
-
const
|
|
1091
|
-
|
|
1092
|
-
const
|
|
1093
|
-
const
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
serializer.addAttributeFilter('data-mce-object', (nodes, name) => {
|
|
1108
|
-
var _a;
|
|
1109
|
-
let i = nodes.length;
|
|
1110
|
-
while (i--) {
|
|
1111
|
-
const node = nodes[i];
|
|
1112
|
-
if (!node.parent) {
|
|
1113
|
-
continue;
|
|
1304
|
+
const buildMediaElement = (editor, node) => {
|
|
1305
|
+
var _a;
|
|
1306
|
+
const realElmName = node.attr('data-mce-object');
|
|
1307
|
+
const element = document.createElement(realElmName);
|
|
1308
|
+
// Add width/height to everything but audio
|
|
1309
|
+
if (realElmName !== 'audio') {
|
|
1310
|
+
const className = node.attr('class');
|
|
1311
|
+
const firstChild = node.firstChild;
|
|
1312
|
+
if (className && className.indexOf('mce-preview-object') !== -1 && firstChild) {
|
|
1313
|
+
const width = firstChild.attr('width');
|
|
1314
|
+
const height = firstChild.attr('height');
|
|
1315
|
+
if (isString(width)) {
|
|
1316
|
+
element.setAttribute('width', width);
|
|
1317
|
+
}
|
|
1318
|
+
if (isString(height)) {
|
|
1319
|
+
element.setAttribute('height', height);
|
|
1320
|
+
}
|
|
1114
1321
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
}
|
|
1124
|
-
} else {
|
|
1125
|
-
realElm.attr({
|
|
1126
|
-
width: node.attr('width'),
|
|
1127
|
-
height: node.attr('height')
|
|
1128
|
-
});
|
|
1129
|
-
}
|
|
1322
|
+
else {
|
|
1323
|
+
const width = node.attr('width');
|
|
1324
|
+
const height = node.attr('height');
|
|
1325
|
+
if (isString(width)) {
|
|
1326
|
+
element.setAttribute('width', width);
|
|
1327
|
+
}
|
|
1328
|
+
if (isString(height)) {
|
|
1329
|
+
element.setAttribute('height', height);
|
|
1330
|
+
}
|
|
1130
1331
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1332
|
+
}
|
|
1333
|
+
const style = node.attr('style');
|
|
1334
|
+
if (isString(style)) {
|
|
1335
|
+
element.setAttribute('style', style);
|
|
1336
|
+
}
|
|
1337
|
+
// Unprefix all placeholder attributes
|
|
1338
|
+
const attribs = (_a = node.attributes) !== null && _a !== void 0 ? _a : [];
|
|
1339
|
+
let ai = attribs.length;
|
|
1340
|
+
while (ai--) {
|
|
1341
|
+
const attrName = attribs[ai].name;
|
|
1342
|
+
if (attrName.indexOf('data-mce-p-') === 0) {
|
|
1343
|
+
element.setAttribute(attrName.substr(11), attribs[ai].value);
|
|
1139
1344
|
}
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1345
|
+
}
|
|
1346
|
+
// Inject innerhtml
|
|
1347
|
+
const innerHtml = node.attr('data-mce-html');
|
|
1348
|
+
if (isString(innerHtml)) {
|
|
1349
|
+
element.innerHTML = unescape(innerHtml);
|
|
1350
|
+
}
|
|
1351
|
+
else {
|
|
1352
|
+
element.innerHTML = '\u00a0';
|
|
1353
|
+
}
|
|
1354
|
+
const fragment = parseAndSanitize(editor, element.outerHTML);
|
|
1355
|
+
const newElement = fragment.getAll(realElmName)[0];
|
|
1356
|
+
if (isNonNullable(newElement)) {
|
|
1357
|
+
if (!isString(innerHtml)) {
|
|
1358
|
+
newElement.empty();
|
|
1144
1359
|
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1360
|
+
return Optional.some(newElement);
|
|
1361
|
+
}
|
|
1362
|
+
else {
|
|
1363
|
+
return Optional.none();
|
|
1364
|
+
}
|
|
1365
|
+
};
|
|
1366
|
+
const setup$1 = (editor) => {
|
|
1367
|
+
editor.on('PreInit', () => {
|
|
1368
|
+
const { schema, serializer, parser } = editor;
|
|
1369
|
+
// Set browser specific allowFullscreen attribs as boolean
|
|
1370
|
+
const boolAttrs = schema.getBoolAttrs();
|
|
1371
|
+
each$1('webkitallowfullscreen mozallowfullscreen'.split(' '), (name) => {
|
|
1372
|
+
boolAttrs[name] = {};
|
|
1373
|
+
});
|
|
1374
|
+
// Add some non-standard attributes to the schema
|
|
1375
|
+
each({
|
|
1376
|
+
embed: ['wmode']
|
|
1377
|
+
}, (attrs, name) => {
|
|
1378
|
+
const rule = schema.getElementRule(name);
|
|
1379
|
+
if (rule) {
|
|
1380
|
+
each$1(attrs, (attr) => {
|
|
1381
|
+
rule.attributes[attr] = {};
|
|
1382
|
+
rule.attributesOrder.push(attr);
|
|
1383
|
+
});
|
|
1384
|
+
}
|
|
1385
|
+
});
|
|
1386
|
+
// Converts iframe, video etc into placeholder images
|
|
1387
|
+
parser.addNodeFilter('iframe,video,audio,object,embed', placeHolderConverter(editor));
|
|
1388
|
+
// Replaces placeholder images with real elements for video, object, iframe etc
|
|
1389
|
+
serializer.addAttributeFilter('data-mce-object', (nodes) => {
|
|
1390
|
+
let i = nodes.length;
|
|
1391
|
+
while (i--) {
|
|
1392
|
+
const node = nodes[i];
|
|
1393
|
+
if (!node.parent) {
|
|
1394
|
+
continue;
|
|
1395
|
+
}
|
|
1396
|
+
buildMediaElement(editor, node).fold(() => node.remove(), (realElm) => node.replace(realElm));
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1147
1399
|
});
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1400
|
+
editor.on('SetContent', () => {
|
|
1401
|
+
// TODO: This shouldn't be needed there should be a way to mark bogus
|
|
1402
|
+
// elements so they are never removed except external save
|
|
1403
|
+
const dom = editor.dom;
|
|
1404
|
+
each$1(dom.select('span.mce-preview-object'), (elm) => {
|
|
1405
|
+
if (dom.select('span.mce-shim', elm).length === 0) {
|
|
1406
|
+
dom.add(elm, 'span', { class: 'mce-shim' });
|
|
1407
|
+
}
|
|
1408
|
+
});
|
|
1155
1409
|
});
|
|
1156
|
-
});
|
|
1157
1410
|
};
|
|
1158
1411
|
|
|
1159
|
-
const setup = editor => {
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1412
|
+
const setup = (editor) => {
|
|
1413
|
+
editor.on('ResolveName', (e) => {
|
|
1414
|
+
let name;
|
|
1415
|
+
if (e.target.nodeType === 1 && (name = e.target.getAttribute('data-mce-object'))) {
|
|
1416
|
+
e.name = name;
|
|
1417
|
+
}
|
|
1418
|
+
});
|
|
1166
1419
|
};
|
|
1167
1420
|
|
|
1168
|
-
const onSetupEditable = editor => api => {
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1421
|
+
const onSetupEditable = (editor) => (api) => {
|
|
1422
|
+
const nodeChanged = () => {
|
|
1423
|
+
api.setEnabled(editor.selection.isEditable());
|
|
1424
|
+
};
|
|
1425
|
+
editor.on('NodeChange', nodeChanged);
|
|
1426
|
+
nodeChanged();
|
|
1427
|
+
return () => {
|
|
1428
|
+
editor.off('NodeChange', nodeChanged);
|
|
1429
|
+
};
|
|
1177
1430
|
};
|
|
1178
|
-
const register = editor => {
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1431
|
+
const register = (editor) => {
|
|
1432
|
+
const onAction = () => editor.execCommand('mceMedia');
|
|
1433
|
+
editor.ui.registry.addToggleButton('media', {
|
|
1434
|
+
tooltip: 'Insert/edit media',
|
|
1435
|
+
icon: 'embed',
|
|
1436
|
+
onAction,
|
|
1437
|
+
onSetup: (buttonApi) => {
|
|
1438
|
+
const selection = editor.selection;
|
|
1439
|
+
buttonApi.setActive(isMediaElement(selection.getNode()));
|
|
1440
|
+
const unbindSelectorChanged = selection.selectorChangedWithUnbind('img[data-mce-object],span[data-mce-object],div[data-ephox-embed-iri]', buttonApi.setActive).unbind;
|
|
1441
|
+
const unbindEditable = onSetupEditable(editor)(buttonApi);
|
|
1442
|
+
return () => {
|
|
1443
|
+
unbindSelectorChanged();
|
|
1444
|
+
unbindEditable();
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
editor.ui.registry.addMenuItem('media', {
|
|
1449
|
+
icon: 'embed',
|
|
1450
|
+
text: 'Media...',
|
|
1451
|
+
onAction,
|
|
1452
|
+
onSetup: onSetupEditable(editor)
|
|
1453
|
+
});
|
|
1201
1454
|
};
|
|
1202
1455
|
|
|
1203
1456
|
var Plugin = () => {
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1457
|
+
global$6.add('media', (editor) => {
|
|
1458
|
+
register$2(editor);
|
|
1459
|
+
register$1(editor);
|
|
1460
|
+
register(editor);
|
|
1461
|
+
setup(editor);
|
|
1462
|
+
setup$1(editor);
|
|
1463
|
+
setup$2(editor);
|
|
1464
|
+
return get(editor);
|
|
1465
|
+
});
|
|
1213
1466
|
};
|
|
1214
1467
|
|
|
1215
1468
|
Plugin();
|
|
1469
|
+
/** *****
|
|
1470
|
+
* DO NOT EXPORT ANYTHING
|
|
1471
|
+
*
|
|
1472
|
+
* IF YOU DO ROLLUP WILL LEAVE A GLOBAL ON THE PAGE
|
|
1473
|
+
*******/
|
|
1216
1474
|
|
|
1217
1475
|
})();
|