fx-platform-ui 0.0.13-alpha14 → 0.0.13-alpha15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/fx-platform-ui.mjs +37583 -21323
- package/lib/fx-platform-ui.umd.js +75 -32
- package/lib/style.css +1 -1
- package/lib/tinymce/CHANGELOG.md +2957 -0
- package/lib/tinymce/README.md +71 -0
- package/lib/tinymce/bower.json +27 -0
- package/lib/tinymce/composer.json +52 -0
- package/lib/tinymce/icons/default/icons.js +182 -0
- package/lib/tinymce/icons/default/icons.min.js +1 -0
- package/lib/tinymce/icons/default/index.js +7 -0
- package/lib/tinymce/license.txt +21 -0
- package/lib/tinymce/models/dom/index.js +7 -0
- package/lib/tinymce/models/dom/model.js +7975 -0
- package/lib/tinymce/models/dom/model.min.js +4 -0
- package/lib/tinymce/package.json +32 -0
- package/lib/tinymce/plugins/advlist/index.js +7 -0
- package/lib/tinymce/plugins/advlist/plugin.js +246 -0
- package/lib/tinymce/plugins/advlist/plugin.min.js +4 -0
- package/lib/tinymce/plugins/anchor/index.js +7 -0
- package/lib/tinymce/plugins/anchor/plugin.js +195 -0
- package/lib/tinymce/plugins/anchor/plugin.min.js +4 -0
- package/lib/tinymce/plugins/autolink/index.js +7 -0
- package/lib/tinymce/plugins/autolink/plugin.js +232 -0
- package/lib/tinymce/plugins/autolink/plugin.min.js +4 -0
- package/lib/tinymce/plugins/autoresize/index.js +7 -0
- package/lib/tinymce/plugins/autoresize/plugin.js +156 -0
- package/lib/tinymce/plugins/autoresize/plugin.min.js +4 -0
- package/lib/tinymce/plugins/autosave/index.js +7 -0
- package/lib/tinymce/plugins/autosave/plugin.js +232 -0
- package/lib/tinymce/plugins/autosave/plugin.min.js +4 -0
- package/lib/tinymce/plugins/charmap/index.js +7 -0
- package/lib/tinymce/plugins/charmap/plugin.js +1636 -0
- package/lib/tinymce/plugins/charmap/plugin.min.js +4 -0
- package/lib/tinymce/plugins/code/index.js +7 -0
- package/lib/tinymce/plugins/code/plugin.js +85 -0
- package/lib/tinymce/plugins/code/plugin.min.js +4 -0
- package/lib/tinymce/plugins/codesample/index.js +7 -0
- package/lib/tinymce/plugins/codesample/plugin.js +2451 -0
- package/lib/tinymce/plugins/codesample/plugin.min.js +4 -0
- package/lib/tinymce/plugins/directionality/index.js +7 -0
- package/lib/tinymce/plugins/directionality/plugin.js +384 -0
- package/lib/tinymce/plugins/directionality/plugin.min.js +4 -0
- package/lib/tinymce/plugins/emoticons/index.js +7 -0
- package/lib/tinymce/plugins/emoticons/js/emojiimages.js +1 -0
- package/lib/tinymce/plugins/emoticons/js/emojiimages.min.js +3 -0
- package/lib/tinymce/plugins/emoticons/js/emojis.js +1 -0
- package/lib/tinymce/plugins/emoticons/js/emojis.min.js +2 -0
- package/lib/tinymce/plugins/emoticons/plugin.js +577 -0
- package/lib/tinymce/plugins/emoticons/plugin.min.js +4 -0
- package/lib/tinymce/plugins/fullscreen/index.js +7 -0
- package/lib/tinymce/plugins/fullscreen/plugin.js +1190 -0
- package/lib/tinymce/plugins/fullscreen/plugin.min.js +4 -0
- package/lib/tinymce/plugins/help/index.js +7 -0
- package/lib/tinymce/plugins/help/plugin.js +848 -0
- package/lib/tinymce/plugins/help/plugin.min.js +4 -0
- package/lib/tinymce/plugins/image/index.js +7 -0
- package/lib/tinymce/plugins/image/plugin.js +1475 -0
- package/lib/tinymce/plugins/image/plugin.min.js +4 -0
- package/lib/tinymce/plugins/importcss/index.js +7 -0
- package/lib/tinymce/plugins/importcss/plugin.js +342 -0
- package/lib/tinymce/plugins/importcss/plugin.min.js +4 -0
- package/lib/tinymce/plugins/insertdatetime/index.js +7 -0
- package/lib/tinymce/plugins/insertdatetime/plugin.js +176 -0
- package/lib/tinymce/plugins/insertdatetime/plugin.min.js +4 -0
- package/lib/tinymce/plugins/link/index.js +7 -0
- package/lib/tinymce/plugins/link/plugin.js +1190 -0
- package/lib/tinymce/plugins/link/plugin.min.js +4 -0
- package/lib/tinymce/plugins/lists/index.js +7 -0
- package/lib/tinymce/plugins/lists/plugin.js +1820 -0
- package/lib/tinymce/plugins/lists/plugin.min.js +4 -0
- package/lib/tinymce/plugins/media/index.js +7 -0
- package/lib/tinymce/plugins/media/plugin.js +1157 -0
- package/lib/tinymce/plugins/media/plugin.min.js +4 -0
- package/lib/tinymce/plugins/nonbreaking/index.js +7 -0
- package/lib/tinymce/plugins/nonbreaking/plugin.js +111 -0
- package/lib/tinymce/plugins/nonbreaking/plugin.min.js +4 -0
- package/lib/tinymce/plugins/pagebreak/index.js +7 -0
- package/lib/tinymce/plugins/pagebreak/plugin.js +105 -0
- package/lib/tinymce/plugins/pagebreak/plugin.min.js +4 -0
- package/lib/tinymce/plugins/preview/index.js +7 -0
- package/lib/tinymce/plugins/preview/plugin.js +97 -0
- package/lib/tinymce/plugins/preview/plugin.min.js +4 -0
- package/lib/tinymce/plugins/quickbars/index.js +7 -0
- package/lib/tinymce/plugins/quickbars/plugin.js +421 -0
- package/lib/tinymce/plugins/quickbars/plugin.min.js +4 -0
- package/lib/tinymce/plugins/save/index.js +7 -0
- package/lib/tinymce/plugins/save/plugin.js +118 -0
- package/lib/tinymce/plugins/save/plugin.min.js +4 -0
- package/lib/tinymce/plugins/searchreplace/index.js +7 -0
- package/lib/tinymce/plugins/searchreplace/plugin.js +1079 -0
- package/lib/tinymce/plugins/searchreplace/plugin.min.js +4 -0
- package/lib/tinymce/plugins/table/index.js +7 -0
- package/lib/tinymce/plugins/table/plugin.js +3393 -0
- package/lib/tinymce/plugins/table/plugin.min.js +4 -0
- package/lib/tinymce/plugins/template/index.js +7 -0
- package/lib/tinymce/plugins/template/plugin.js +548 -0
- package/lib/tinymce/plugins/template/plugin.min.js +4 -0
- package/lib/tinymce/plugins/visualblocks/index.js +7 -0
- package/lib/tinymce/plugins/visualblocks/plugin.js +98 -0
- package/lib/tinymce/plugins/visualblocks/plugin.min.js +4 -0
- package/lib/tinymce/plugins/visualchars/index.js +7 -0
- package/lib/tinymce/plugins/visualchars/plugin.js +506 -0
- package/lib/tinymce/plugins/visualchars/plugin.min.js +4 -0
- package/lib/tinymce/plugins/wordcount/index.js +7 -0
- package/lib/tinymce/plugins/wordcount/plugin.js +404 -0
- package/lib/tinymce/plugins/wordcount/plugin.min.js +4 -0
- package/lib/tinymce/themes/silver/index.js +7 -0
- package/lib/tinymce/themes/silver/theme.js +26184 -0
- package/lib/tinymce/themes/silver/theme.min.js +4 -0
- package/lib/tinymce/tinymce.d.ts +2895 -0
- package/lib/tinymce/tinymce.js +29400 -0
- package/package.json +1 -1
- package/packages/components/editor/src/hook/useEditorState.ts +3 -3
- package/packages/components/editor/src/index.vue +2 -2
|
@@ -0,0 +1,1157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TinyMCE version 6.1.2 (2022-07-29)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
(function () {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
var global$6 = tinymce.util.Tools.resolve('tinymce.PluginManager');
|
|
9
|
+
|
|
10
|
+
const hasProto = (v, constructor, predicate) => {
|
|
11
|
+
var _a;
|
|
12
|
+
if (predicate(v, constructor.prototype)) {
|
|
13
|
+
return true;
|
|
14
|
+
} else {
|
|
15
|
+
return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const typeOf = x => {
|
|
19
|
+
const t = typeof x;
|
|
20
|
+
if (x === null) {
|
|
21
|
+
return 'null';
|
|
22
|
+
} else if (t === 'object' && Array.isArray(x)) {
|
|
23
|
+
return 'array';
|
|
24
|
+
} else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
|
|
25
|
+
return 'string';
|
|
26
|
+
} else {
|
|
27
|
+
return t;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const isType = type => value => typeOf(value) === type;
|
|
31
|
+
const isString = isType('string');
|
|
32
|
+
const isObject = isType('object');
|
|
33
|
+
const isArray = isType('array');
|
|
34
|
+
const isNullable = a => a === null || a === undefined;
|
|
35
|
+
const isNonNullable = a => !isNullable(a);
|
|
36
|
+
|
|
37
|
+
class Optional {
|
|
38
|
+
constructor(tag, value) {
|
|
39
|
+
this.tag = tag;
|
|
40
|
+
this.value = value;
|
|
41
|
+
}
|
|
42
|
+
static some(value) {
|
|
43
|
+
return new Optional(true, value);
|
|
44
|
+
}
|
|
45
|
+
static none() {
|
|
46
|
+
return Optional.singletonNone;
|
|
47
|
+
}
|
|
48
|
+
fold(onNone, onSome) {
|
|
49
|
+
if (this.tag) {
|
|
50
|
+
return onSome(this.value);
|
|
51
|
+
} else {
|
|
52
|
+
return onNone();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
isSome() {
|
|
56
|
+
return this.tag;
|
|
57
|
+
}
|
|
58
|
+
isNone() {
|
|
59
|
+
return !this.tag;
|
|
60
|
+
}
|
|
61
|
+
map(mapper) {
|
|
62
|
+
if (this.tag) {
|
|
63
|
+
return Optional.some(mapper(this.value));
|
|
64
|
+
} else {
|
|
65
|
+
return Optional.none();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
bind(binder) {
|
|
69
|
+
if (this.tag) {
|
|
70
|
+
return binder(this.value);
|
|
71
|
+
} else {
|
|
72
|
+
return Optional.none();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exists(predicate) {
|
|
76
|
+
return this.tag && predicate(this.value);
|
|
77
|
+
}
|
|
78
|
+
forall(predicate) {
|
|
79
|
+
return !this.tag || predicate(this.value);
|
|
80
|
+
}
|
|
81
|
+
filter(predicate) {
|
|
82
|
+
if (!this.tag || predicate(this.value)) {
|
|
83
|
+
return this;
|
|
84
|
+
} else {
|
|
85
|
+
return Optional.none();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
getOr(replacement) {
|
|
89
|
+
return this.tag ? this.value : replacement;
|
|
90
|
+
}
|
|
91
|
+
or(replacement) {
|
|
92
|
+
return this.tag ? this : replacement;
|
|
93
|
+
}
|
|
94
|
+
getOrThunk(thunk) {
|
|
95
|
+
return this.tag ? this.value : thunk();
|
|
96
|
+
}
|
|
97
|
+
orThunk(thunk) {
|
|
98
|
+
return this.tag ? this : thunk();
|
|
99
|
+
}
|
|
100
|
+
getOrDie(message) {
|
|
101
|
+
if (!this.tag) {
|
|
102
|
+
throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
|
|
103
|
+
} else {
|
|
104
|
+
return this.value;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
static from(value) {
|
|
108
|
+
return isNonNullable(value) ? Optional.some(value) : Optional.none();
|
|
109
|
+
}
|
|
110
|
+
getOrNull() {
|
|
111
|
+
return this.tag ? this.value : null;
|
|
112
|
+
}
|
|
113
|
+
getOrUndefined() {
|
|
114
|
+
return this.value;
|
|
115
|
+
}
|
|
116
|
+
each(worker) {
|
|
117
|
+
if (this.tag) {
|
|
118
|
+
worker(this.value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
toArray() {
|
|
122
|
+
return this.tag ? [this.value] : [];
|
|
123
|
+
}
|
|
124
|
+
toString() {
|
|
125
|
+
return this.tag ? `some(${ this.value })` : 'none()';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
Optional.singletonNone = new Optional(false);
|
|
129
|
+
|
|
130
|
+
const nativePush = Array.prototype.push;
|
|
131
|
+
const each$1 = (xs, f) => {
|
|
132
|
+
for (let i = 0, len = xs.length; i < len; i++) {
|
|
133
|
+
const x = xs[i];
|
|
134
|
+
f(x, i);
|
|
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;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const Cell = initial => {
|
|
149
|
+
let value = initial;
|
|
150
|
+
const get = () => {
|
|
151
|
+
return value;
|
|
152
|
+
};
|
|
153
|
+
const set = v => {
|
|
154
|
+
value = v;
|
|
155
|
+
};
|
|
156
|
+
return {
|
|
157
|
+
get,
|
|
158
|
+
set
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const keys = Object.keys;
|
|
163
|
+
const hasOwnProperty = Object.hasOwnProperty;
|
|
164
|
+
const each = (obj, f) => {
|
|
165
|
+
const props = keys(obj);
|
|
166
|
+
for (let k = 0, len = props.length; k < len; k++) {
|
|
167
|
+
const i = props[k];
|
|
168
|
+
const x = obj[i];
|
|
169
|
+
f(x, i);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
const get$1 = (obj, key) => {
|
|
173
|
+
return has(obj, key) ? Optional.from(obj[key]) : Optional.none();
|
|
174
|
+
};
|
|
175
|
+
const has = (obj, key) => hasOwnProperty.call(obj, key);
|
|
176
|
+
|
|
177
|
+
const option = name => editor => editor.options.get(name);
|
|
178
|
+
const register$2 = editor => {
|
|
179
|
+
const registerOption = editor.options.register;
|
|
180
|
+
registerOption('audio_template_callback', { processor: 'function' });
|
|
181
|
+
registerOption('video_template_callback', { processor: 'function' });
|
|
182
|
+
registerOption('iframe_template_callback', { processor: 'function' });
|
|
183
|
+
registerOption('media_live_embeds', {
|
|
184
|
+
processor: 'boolean',
|
|
185
|
+
default: true
|
|
186
|
+
});
|
|
187
|
+
registerOption('media_filter_html', {
|
|
188
|
+
processor: 'boolean',
|
|
189
|
+
default: true
|
|
190
|
+
});
|
|
191
|
+
registerOption('media_url_resolver', { processor: 'function' });
|
|
192
|
+
registerOption('media_alt_source', {
|
|
193
|
+
processor: 'boolean',
|
|
194
|
+
default: true
|
|
195
|
+
});
|
|
196
|
+
registerOption('media_poster', {
|
|
197
|
+
processor: 'boolean',
|
|
198
|
+
default: true
|
|
199
|
+
});
|
|
200
|
+
registerOption('media_dimensions', {
|
|
201
|
+
processor: 'boolean',
|
|
202
|
+
default: true
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
const getAudioTemplateCallback = option('audio_template_callback');
|
|
206
|
+
const getVideoTemplateCallback = option('video_template_callback');
|
|
207
|
+
const getIframeTemplateCallback = option('iframe_template_callback');
|
|
208
|
+
const hasLiveEmbeds = option('media_live_embeds');
|
|
209
|
+
const shouldFilterHtml = option('media_filter_html');
|
|
210
|
+
const getUrlResolver = option('media_url_resolver');
|
|
211
|
+
const hasAltSource = option('media_alt_source');
|
|
212
|
+
const hasPoster = option('media_poster');
|
|
213
|
+
const hasDimensions = option('media_dimensions');
|
|
214
|
+
|
|
215
|
+
var global$5 = tinymce.util.Tools.resolve('tinymce.util.Tools');
|
|
216
|
+
|
|
217
|
+
var global$4 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
|
|
218
|
+
|
|
219
|
+
var global$3 = tinymce.util.Tools.resolve('tinymce.html.DomParser');
|
|
220
|
+
|
|
221
|
+
const DOM$1 = global$4.DOM;
|
|
222
|
+
const trimPx = value => value.replace(/px$/, '');
|
|
223
|
+
const getEphoxEmbedData = node => {
|
|
224
|
+
const style = node.attr('style');
|
|
225
|
+
const styles = style ? DOM$1.parseStyle(style) : {};
|
|
226
|
+
return {
|
|
227
|
+
type: 'ephox-embed-iri',
|
|
228
|
+
source: node.attr('data-ephox-embed-iri'),
|
|
229
|
+
altsource: '',
|
|
230
|
+
poster: '',
|
|
231
|
+
width: get$1(styles, 'max-width').map(trimPx).getOr(''),
|
|
232
|
+
height: get$1(styles, 'max-height').map(trimPx).getOr('')
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
const htmlToData = (html, schema) => {
|
|
236
|
+
let data = {};
|
|
237
|
+
const parser = global$3({
|
|
238
|
+
validate: false,
|
|
239
|
+
forced_root_block: false
|
|
240
|
+
}, schema);
|
|
241
|
+
const rootNode = parser.parse(html);
|
|
242
|
+
for (let node = rootNode; node; node = node.walk()) {
|
|
243
|
+
if (node.type === 1) {
|
|
244
|
+
const name = node.name;
|
|
245
|
+
if (node.attr('data-ephox-embed-iri')) {
|
|
246
|
+
data = getEphoxEmbedData(node);
|
|
247
|
+
break;
|
|
248
|
+
} else {
|
|
249
|
+
if (!data.source && name === 'param') {
|
|
250
|
+
data.source = node.attr('movie');
|
|
251
|
+
}
|
|
252
|
+
if (name === 'iframe' || name === 'object' || name === 'embed' || name === 'video' || name === 'audio') {
|
|
253
|
+
if (!data.type) {
|
|
254
|
+
data.type = name;
|
|
255
|
+
}
|
|
256
|
+
data = global$5.extend(node.attributes.map, data);
|
|
257
|
+
}
|
|
258
|
+
if (name === 'script') {
|
|
259
|
+
data = {
|
|
260
|
+
type: 'script',
|
|
261
|
+
source: node.attr('src')
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
if (name === 'source') {
|
|
265
|
+
if (!data.source) {
|
|
266
|
+
data.source = node.attr('src');
|
|
267
|
+
} else if (!data.altsource) {
|
|
268
|
+
data.altsource = node.attr('src');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (name === 'img' && !data.poster) {
|
|
272
|
+
data.poster = node.attr('src');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
data.source = data.source || data.src || data.data;
|
|
278
|
+
data.altsource = data.altsource || '';
|
|
279
|
+
data.poster = data.poster || '';
|
|
280
|
+
return data;
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
const guess = url => {
|
|
284
|
+
const mimes = {
|
|
285
|
+
mp3: 'audio/mpeg',
|
|
286
|
+
m4a: 'audio/x-m4a',
|
|
287
|
+
wav: 'audio/wav',
|
|
288
|
+
mp4: 'video/mp4',
|
|
289
|
+
webm: 'video/webm',
|
|
290
|
+
ogg: 'video/ogg',
|
|
291
|
+
swf: 'application/x-shockwave-flash'
|
|
292
|
+
};
|
|
293
|
+
const fileEnd = url.toLowerCase().split('.').pop();
|
|
294
|
+
const mime = mimes[fileEnd];
|
|
295
|
+
return mime ? mime : '';
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
var global$2 = tinymce.util.Tools.resolve('tinymce.html.Node');
|
|
299
|
+
|
|
300
|
+
var global$1 = tinymce.util.Tools.resolve('tinymce.html.Serializer');
|
|
301
|
+
|
|
302
|
+
const Parser = (schema, settings = {}) => global$3({
|
|
303
|
+
forced_root_block: false,
|
|
304
|
+
validate: false,
|
|
305
|
+
allow_conditional_comments: true,
|
|
306
|
+
...settings
|
|
307
|
+
}, schema);
|
|
308
|
+
|
|
309
|
+
const DOM = global$4.DOM;
|
|
310
|
+
const addPx = value => /^[0-9.]+$/.test(value) ? value + 'px' : value;
|
|
311
|
+
const updateEphoxEmbed = (data, node) => {
|
|
312
|
+
const style = node.attr('style');
|
|
313
|
+
const styleMap = style ? DOM.parseStyle(style) : {};
|
|
314
|
+
styleMap['max-width'] = addPx(data.width);
|
|
315
|
+
styleMap['max-height'] = addPx(data.height);
|
|
316
|
+
node.attr('style', DOM.serializeStyle(styleMap));
|
|
317
|
+
};
|
|
318
|
+
const sources = [
|
|
319
|
+
'source',
|
|
320
|
+
'altsource'
|
|
321
|
+
];
|
|
322
|
+
const updateHtml = (html, data, updateAll, schema) => {
|
|
323
|
+
let numSources = 0;
|
|
324
|
+
let sourceCount = 0;
|
|
325
|
+
const parser = Parser(schema);
|
|
326
|
+
parser.addNodeFilter('source', nodes => numSources = nodes.length);
|
|
327
|
+
const rootNode = parser.parse(html);
|
|
328
|
+
for (let node = rootNode; node; node = node.walk()) {
|
|
329
|
+
if (node.type === 1) {
|
|
330
|
+
const name = node.name;
|
|
331
|
+
if (node.attr('data-ephox-embed-iri')) {
|
|
332
|
+
updateEphoxEmbed(data, node);
|
|
333
|
+
break;
|
|
334
|
+
} else {
|
|
335
|
+
switch (name) {
|
|
336
|
+
case 'video':
|
|
337
|
+
case 'object':
|
|
338
|
+
case 'embed':
|
|
339
|
+
case 'img':
|
|
340
|
+
case 'iframe':
|
|
341
|
+
if (data.height !== undefined && data.width !== undefined) {
|
|
342
|
+
node.attr('width', data.width);
|
|
343
|
+
node.attr('height', data.height);
|
|
344
|
+
}
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
if (updateAll) {
|
|
348
|
+
switch (name) {
|
|
349
|
+
case 'video':
|
|
350
|
+
node.attr('poster', data.poster);
|
|
351
|
+
node.attr('src', null);
|
|
352
|
+
for (let index = numSources; index < 2; index++) {
|
|
353
|
+
if (data[sources[index]]) {
|
|
354
|
+
const source = new global$2('source', 1);
|
|
355
|
+
source.attr('src', data[sources[index]]);
|
|
356
|
+
source.attr('type', data[sources[index] + 'mime'] || null);
|
|
357
|
+
node.append(source);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
case 'iframe':
|
|
362
|
+
node.attr('src', data.source);
|
|
363
|
+
break;
|
|
364
|
+
case 'object':
|
|
365
|
+
const hasImage = node.getAll('img').length > 0;
|
|
366
|
+
if (data.poster && !hasImage) {
|
|
367
|
+
node.attr('src', data.poster);
|
|
368
|
+
const img = new global$2('img', 1);
|
|
369
|
+
img.attr('src', data.poster);
|
|
370
|
+
img.attr('width', data.width);
|
|
371
|
+
img.attr('height', data.height);
|
|
372
|
+
node.append(img);
|
|
373
|
+
}
|
|
374
|
+
break;
|
|
375
|
+
case 'source':
|
|
376
|
+
if (sourceCount < 2) {
|
|
377
|
+
node.attr('src', data[sources[sourceCount]]);
|
|
378
|
+
node.attr('type', data[sources[sourceCount] + 'mime'] || null);
|
|
379
|
+
if (!data[sources[sourceCount]]) {
|
|
380
|
+
node.remove();
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
sourceCount++;
|
|
385
|
+
break;
|
|
386
|
+
case 'img':
|
|
387
|
+
if (!data.poster) {
|
|
388
|
+
node.remove();
|
|
389
|
+
}
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return global$1({}, schema).serialize(rootNode);
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
const urlPatterns = [
|
|
400
|
+
{
|
|
401
|
+
regex: /youtu\.be\/([\w\-_\?&=.]+)/i,
|
|
402
|
+
type: 'iframe',
|
|
403
|
+
w: 560,
|
|
404
|
+
h: 314,
|
|
405
|
+
url: 'www.youtube.com/embed/$1',
|
|
406
|
+
allowFullscreen: true
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
regex: /youtube\.com(.+)v=([^&]+)(&([a-z0-9&=\-_]+))?/i,
|
|
410
|
+
type: 'iframe',
|
|
411
|
+
w: 560,
|
|
412
|
+
h: 314,
|
|
413
|
+
url: 'www.youtube.com/embed/$2?$4',
|
|
414
|
+
allowFullscreen: true
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
regex: /youtube.com\/embed\/([a-z0-9\?&=\-_]+)/i,
|
|
418
|
+
type: 'iframe',
|
|
419
|
+
w: 560,
|
|
420
|
+
h: 314,
|
|
421
|
+
url: 'www.youtube.com/embed/$1',
|
|
422
|
+
allowFullscreen: true
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
regex: /vimeo\.com\/([0-9]+)/,
|
|
426
|
+
type: 'iframe',
|
|
427
|
+
w: 425,
|
|
428
|
+
h: 350,
|
|
429
|
+
url: 'player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc',
|
|
430
|
+
allowFullscreen: true
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
regex: /vimeo\.com\/(.*)\/([0-9]+)/,
|
|
434
|
+
type: 'iframe',
|
|
435
|
+
w: 425,
|
|
436
|
+
h: 350,
|
|
437
|
+
url: 'player.vimeo.com/video/$2?title=0&byline=0',
|
|
438
|
+
allowFullscreen: true
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
regex: /maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,
|
|
442
|
+
type: 'iframe',
|
|
443
|
+
w: 425,
|
|
444
|
+
h: 350,
|
|
445
|
+
url: 'maps.google.com/maps/ms?msid=$2&output=embed"',
|
|
446
|
+
allowFullscreen: false
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
regex: /dailymotion\.com\/video\/([^_]+)/,
|
|
450
|
+
type: 'iframe',
|
|
451
|
+
w: 480,
|
|
452
|
+
h: 270,
|
|
453
|
+
url: 'www.dailymotion.com/embed/video/$1',
|
|
454
|
+
allowFullscreen: true
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
regex: /dai\.ly\/([^_]+)/,
|
|
458
|
+
type: 'iframe',
|
|
459
|
+
w: 480,
|
|
460
|
+
h: 270,
|
|
461
|
+
url: 'www.dailymotion.com/embed/video/$1',
|
|
462
|
+
allowFullscreen: true
|
|
463
|
+
}
|
|
464
|
+
];
|
|
465
|
+
const getProtocol = url => {
|
|
466
|
+
const protocolMatches = url.match(/^(https?:\/\/|www\.)(.+)$/i);
|
|
467
|
+
if (protocolMatches && protocolMatches.length > 1) {
|
|
468
|
+
return protocolMatches[1] === 'www.' ? 'https://' : protocolMatches[1];
|
|
469
|
+
} else {
|
|
470
|
+
return 'https://';
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
const getUrl = (pattern, url) => {
|
|
474
|
+
const protocol = getProtocol(url);
|
|
475
|
+
const match = pattern.regex.exec(url);
|
|
476
|
+
let newUrl = protocol + pattern.url;
|
|
477
|
+
for (let i = 0; i < match.length; i++) {
|
|
478
|
+
newUrl = newUrl.replace('$' + i, () => match[i] ? match[i] : '');
|
|
479
|
+
}
|
|
480
|
+
return newUrl.replace(/\?$/, '');
|
|
481
|
+
};
|
|
482
|
+
const matchPattern = url => {
|
|
483
|
+
const patterns = urlPatterns.filter(pattern => pattern.regex.test(url));
|
|
484
|
+
if (patterns.length > 0) {
|
|
485
|
+
return global$5.extend({}, patterns[0], { url: getUrl(patterns[0], url) });
|
|
486
|
+
} else {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
const getIframeHtml = (data, iframeTemplateCallback) => {
|
|
492
|
+
if (iframeTemplateCallback) {
|
|
493
|
+
return iframeTemplateCallback(data);
|
|
494
|
+
} else {
|
|
495
|
+
const allowFullscreen = data.allowfullscreen ? ' allowFullscreen="1"' : '';
|
|
496
|
+
return '<iframe src="' + data.source + '" width="' + data.width + '" height="' + data.height + '"' + allowFullscreen + '></iframe>';
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
const getFlashHtml = data => {
|
|
500
|
+
let html = '<object data="' + data.source + '" width="' + data.width + '" height="' + data.height + '" type="application/x-shockwave-flash">';
|
|
501
|
+
if (data.poster) {
|
|
502
|
+
html += '<img src="' + data.poster + '" width="' + data.width + '" height="' + data.height + '" />';
|
|
503
|
+
}
|
|
504
|
+
html += '</object>';
|
|
505
|
+
return html;
|
|
506
|
+
};
|
|
507
|
+
const getAudioHtml = (data, audioTemplateCallback) => {
|
|
508
|
+
if (audioTemplateCallback) {
|
|
509
|
+
return audioTemplateCallback(data);
|
|
510
|
+
} else {
|
|
511
|
+
return '<audio controls="controls" src="' + data.source + '">' + (data.altsource ? '\n<source src="' + data.altsource + '"' + (data.altsourcemime ? ' type="' + data.altsourcemime + '"' : '') + ' />\n' : '') + '</audio>';
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
const getVideoHtml = (data, videoTemplateCallback) => {
|
|
515
|
+
if (videoTemplateCallback) {
|
|
516
|
+
return videoTemplateCallback(data);
|
|
517
|
+
} else {
|
|
518
|
+
return '<video width="' + data.width + '" height="' + data.height + '"' + (data.poster ? ' poster="' + data.poster + '"' : '') + ' controls="controls">\n' + '<source src="' + data.source + '"' + (data.sourcemime ? ' type="' + data.sourcemime + '"' : '') + ' />\n' + (data.altsource ? '<source src="' + data.altsource + '"' + (data.altsourcemime ? ' type="' + data.altsourcemime + '"' : '') + ' />\n' : '') + '</video>';
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
const getScriptHtml = data => {
|
|
522
|
+
return '<script src="' + data.source + '"></script>';
|
|
523
|
+
};
|
|
524
|
+
const dataToHtml = (editor, dataIn) => {
|
|
525
|
+
const data = global$5.extend({}, dataIn);
|
|
526
|
+
if (!data.source) {
|
|
527
|
+
global$5.extend(data, htmlToData(data.embed, editor.schema));
|
|
528
|
+
if (!data.source) {
|
|
529
|
+
return '';
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (!data.altsource) {
|
|
533
|
+
data.altsource = '';
|
|
534
|
+
}
|
|
535
|
+
if (!data.poster) {
|
|
536
|
+
data.poster = '';
|
|
537
|
+
}
|
|
538
|
+
data.source = editor.convertURL(data.source, 'source');
|
|
539
|
+
data.altsource = editor.convertURL(data.altsource, 'source');
|
|
540
|
+
data.sourcemime = guess(data.source);
|
|
541
|
+
data.altsourcemime = guess(data.altsource);
|
|
542
|
+
data.poster = editor.convertURL(data.poster, 'poster');
|
|
543
|
+
const pattern = matchPattern(data.source);
|
|
544
|
+
if (pattern) {
|
|
545
|
+
data.source = pattern.url;
|
|
546
|
+
data.type = pattern.type;
|
|
547
|
+
data.allowfullscreen = pattern.allowFullscreen;
|
|
548
|
+
data.width = data.width || String(pattern.w);
|
|
549
|
+
data.height = data.height || String(pattern.h);
|
|
550
|
+
}
|
|
551
|
+
if (data.embed) {
|
|
552
|
+
return updateHtml(data.embed, data, true, editor.schema);
|
|
553
|
+
} else {
|
|
554
|
+
const audioTemplateCallback = getAudioTemplateCallback(editor);
|
|
555
|
+
const videoTemplateCallback = getVideoTemplateCallback(editor);
|
|
556
|
+
const iframeTemplateCallback = getIframeTemplateCallback(editor);
|
|
557
|
+
data.width = data.width || '300';
|
|
558
|
+
data.height = data.height || '150';
|
|
559
|
+
global$5.each(data, (value, key) => {
|
|
560
|
+
data[key] = editor.dom.encode('' + value);
|
|
561
|
+
});
|
|
562
|
+
if (data.type === 'iframe') {
|
|
563
|
+
return getIframeHtml(data, iframeTemplateCallback);
|
|
564
|
+
} else if (data.sourcemime === 'application/x-shockwave-flash') {
|
|
565
|
+
return getFlashHtml(data);
|
|
566
|
+
} else if (data.sourcemime.indexOf('audio') !== -1) {
|
|
567
|
+
return getAudioHtml(data, audioTemplateCallback);
|
|
568
|
+
} else if (data.type === 'script') {
|
|
569
|
+
return getScriptHtml(data);
|
|
570
|
+
} else {
|
|
571
|
+
return getVideoHtml(data, videoTemplateCallback);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
const isMediaElement = element => element.hasAttribute('data-mce-object') || element.hasAttribute('data-ephox-embed-iri');
|
|
577
|
+
const setup$2 = editor => {
|
|
578
|
+
editor.on('click keyup touchend', () => {
|
|
579
|
+
const selectedNode = editor.selection.getNode();
|
|
580
|
+
if (selectedNode && editor.dom.hasClass(selectedNode, 'mce-preview-object')) {
|
|
581
|
+
if (editor.dom.getAttrib(selectedNode, 'data-mce-selected')) {
|
|
582
|
+
selectedNode.setAttribute('data-mce-selected', '2');
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
editor.on('ObjectSelected', e => {
|
|
587
|
+
const objectType = e.target.getAttribute('data-mce-object');
|
|
588
|
+
if (objectType === 'script') {
|
|
589
|
+
e.preventDefault();
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
editor.on('ObjectResized', e => {
|
|
593
|
+
const target = e.target;
|
|
594
|
+
if (target.getAttribute('data-mce-object')) {
|
|
595
|
+
let html = target.getAttribute('data-mce-html');
|
|
596
|
+
if (html) {
|
|
597
|
+
html = unescape(html);
|
|
598
|
+
target.setAttribute('data-mce-html', escape(updateHtml(html, {
|
|
599
|
+
width: String(e.width),
|
|
600
|
+
height: String(e.height)
|
|
601
|
+
}, false, editor.schema)));
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
const cache = {};
|
|
608
|
+
const embedPromise = (data, dataToHtml, handler) => {
|
|
609
|
+
return new Promise((res, rej) => {
|
|
610
|
+
const wrappedResolve = response => {
|
|
611
|
+
if (response.html) {
|
|
612
|
+
cache[data.source] = response;
|
|
613
|
+
}
|
|
614
|
+
return res({
|
|
615
|
+
url: data.source,
|
|
616
|
+
html: response.html ? response.html : dataToHtml(data)
|
|
617
|
+
});
|
|
618
|
+
};
|
|
619
|
+
if (cache[data.source]) {
|
|
620
|
+
wrappedResolve(cache[data.source]);
|
|
621
|
+
} else {
|
|
622
|
+
handler({ url: data.source }, wrappedResolve, rej);
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
};
|
|
626
|
+
const defaultPromise = (data, dataToHtml) => Promise.resolve({
|
|
627
|
+
html: dataToHtml(data),
|
|
628
|
+
url: data.source
|
|
629
|
+
});
|
|
630
|
+
const loadedData = editor => data => dataToHtml(editor, data);
|
|
631
|
+
const getEmbedHtml = (editor, data) => {
|
|
632
|
+
const embedHandler = getUrlResolver(editor);
|
|
633
|
+
return embedHandler ? embedPromise(data, loadedData(editor), embedHandler) : defaultPromise(data, loadedData(editor));
|
|
634
|
+
};
|
|
635
|
+
const isCached = url => has(cache, url);
|
|
636
|
+
|
|
637
|
+
const extractMeta = (sourceInput, data) => get$1(data, sourceInput).bind(mainData => get$1(mainData, 'meta'));
|
|
638
|
+
const getValue = (data, metaData, sourceInput) => prop => {
|
|
639
|
+
const getFromData = () => get$1(data, prop);
|
|
640
|
+
const getFromMetaData = () => get$1(metaData, prop);
|
|
641
|
+
const getNonEmptyValue = c => get$1(c, 'value').bind(v => v.length > 0 ? Optional.some(v) : Optional.none());
|
|
642
|
+
const getFromValueFirst = () => getFromData().bind(child => isObject(child) ? getNonEmptyValue(child).orThunk(getFromMetaData) : getFromMetaData().orThunk(() => Optional.from(child)));
|
|
643
|
+
const getFromMetaFirst = () => getFromMetaData().orThunk(() => getFromData().bind(child => isObject(child) ? getNonEmptyValue(child) : Optional.from(child)));
|
|
644
|
+
return { [prop]: (prop === sourceInput ? getFromValueFirst() : getFromMetaFirst()).getOr('') };
|
|
645
|
+
};
|
|
646
|
+
const getDimensions = (data, metaData) => {
|
|
647
|
+
const dimensions = {};
|
|
648
|
+
get$1(data, 'dimensions').each(dims => {
|
|
649
|
+
each$1([
|
|
650
|
+
'width',
|
|
651
|
+
'height'
|
|
652
|
+
], prop => {
|
|
653
|
+
get$1(metaData, prop).orThunk(() => get$1(dims, prop)).each(value => dimensions[prop] = value);
|
|
654
|
+
});
|
|
655
|
+
});
|
|
656
|
+
return dimensions;
|
|
657
|
+
};
|
|
658
|
+
const unwrap = (data, sourceInput) => {
|
|
659
|
+
const metaData = sourceInput ? extractMeta(sourceInput, data).getOr({}) : {};
|
|
660
|
+
const get = getValue(data, metaData, sourceInput);
|
|
661
|
+
return {
|
|
662
|
+
...get('source'),
|
|
663
|
+
...get('altsource'),
|
|
664
|
+
...get('poster'),
|
|
665
|
+
...get('embed'),
|
|
666
|
+
...getDimensions(data, metaData)
|
|
667
|
+
};
|
|
668
|
+
};
|
|
669
|
+
const wrap = data => {
|
|
670
|
+
const wrapped = {
|
|
671
|
+
...data,
|
|
672
|
+
source: { value: get$1(data, 'source').getOr('') },
|
|
673
|
+
altsource: { value: get$1(data, 'altsource').getOr('') },
|
|
674
|
+
poster: { value: get$1(data, 'poster').getOr('') }
|
|
675
|
+
};
|
|
676
|
+
each$1([
|
|
677
|
+
'width',
|
|
678
|
+
'height'
|
|
679
|
+
], prop => {
|
|
680
|
+
get$1(data, prop).each(value => {
|
|
681
|
+
const dimensions = wrapped.dimensions || {};
|
|
682
|
+
dimensions[prop] = value;
|
|
683
|
+
wrapped.dimensions = dimensions;
|
|
684
|
+
});
|
|
685
|
+
});
|
|
686
|
+
return wrapped;
|
|
687
|
+
};
|
|
688
|
+
const handleError = editor => error => {
|
|
689
|
+
const errorMessage = error && error.msg ? 'Media embed handler error: ' + error.msg : 'Media embed handler threw unknown error.';
|
|
690
|
+
editor.notificationManager.open({
|
|
691
|
+
type: 'error',
|
|
692
|
+
text: errorMessage
|
|
693
|
+
});
|
|
694
|
+
};
|
|
695
|
+
const getEditorData = editor => {
|
|
696
|
+
const element = editor.selection.getNode();
|
|
697
|
+
const snippet = isMediaElement(element) ? editor.serializer.serialize(element, { selection: true }) : '';
|
|
698
|
+
return {
|
|
699
|
+
embed: snippet,
|
|
700
|
+
...htmlToData(snippet, editor.schema)
|
|
701
|
+
};
|
|
702
|
+
};
|
|
703
|
+
const addEmbedHtml = (api, editor) => response => {
|
|
704
|
+
if (isString(response.url) && response.url.trim().length > 0) {
|
|
705
|
+
const html = response.html;
|
|
706
|
+
const snippetData = htmlToData(html, editor.schema);
|
|
707
|
+
const nuData = {
|
|
708
|
+
...snippetData,
|
|
709
|
+
source: response.url,
|
|
710
|
+
embed: html
|
|
711
|
+
};
|
|
712
|
+
api.setData(wrap(nuData));
|
|
713
|
+
}
|
|
714
|
+
};
|
|
715
|
+
const selectPlaceholder = (editor, beforeObjects) => {
|
|
716
|
+
const afterObjects = editor.dom.select('*[data-mce-object]');
|
|
717
|
+
for (let i = 0; i < beforeObjects.length; i++) {
|
|
718
|
+
for (let y = afterObjects.length - 1; y >= 0; y--) {
|
|
719
|
+
if (beforeObjects[i] === afterObjects[y]) {
|
|
720
|
+
afterObjects.splice(y, 1);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
editor.selection.select(afterObjects[0]);
|
|
725
|
+
};
|
|
726
|
+
const handleInsert = (editor, html) => {
|
|
727
|
+
const beforeObjects = editor.dom.select('*[data-mce-object]');
|
|
728
|
+
editor.insertContent(html);
|
|
729
|
+
selectPlaceholder(editor, beforeObjects);
|
|
730
|
+
editor.nodeChanged();
|
|
731
|
+
};
|
|
732
|
+
const submitForm = (prevData, newData, editor) => {
|
|
733
|
+
newData.embed = updateHtml(newData.embed, newData, false, editor.schema);
|
|
734
|
+
if (newData.embed && (prevData.source === newData.source || isCached(newData.source))) {
|
|
735
|
+
handleInsert(editor, newData.embed);
|
|
736
|
+
} else {
|
|
737
|
+
getEmbedHtml(editor, newData).then(response => {
|
|
738
|
+
handleInsert(editor, response.html);
|
|
739
|
+
}).catch(handleError(editor));
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
const showDialog = editor => {
|
|
743
|
+
const editorData = getEditorData(editor);
|
|
744
|
+
const currentData = Cell(editorData);
|
|
745
|
+
const initialData = wrap(editorData);
|
|
746
|
+
const handleSource = (prevData, api) => {
|
|
747
|
+
const serviceData = unwrap(api.getData(), 'source');
|
|
748
|
+
if (prevData.source !== serviceData.source) {
|
|
749
|
+
addEmbedHtml(win, editor)({
|
|
750
|
+
url: serviceData.source,
|
|
751
|
+
html: ''
|
|
752
|
+
});
|
|
753
|
+
getEmbedHtml(editor, serviceData).then(addEmbedHtml(win, editor)).catch(handleError(editor));
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
const handleEmbed = api => {
|
|
757
|
+
const data = unwrap(api.getData());
|
|
758
|
+
const dataFromEmbed = htmlToData(data.embed, editor.schema);
|
|
759
|
+
api.setData(wrap(dataFromEmbed));
|
|
760
|
+
};
|
|
761
|
+
const handleUpdate = (api, sourceInput) => {
|
|
762
|
+
const data = unwrap(api.getData(), sourceInput);
|
|
763
|
+
const embed = dataToHtml(editor, data);
|
|
764
|
+
api.setData(wrap({
|
|
765
|
+
...data,
|
|
766
|
+
embed
|
|
767
|
+
}));
|
|
768
|
+
};
|
|
769
|
+
const mediaInput = [{
|
|
770
|
+
name: 'source',
|
|
771
|
+
type: 'urlinput',
|
|
772
|
+
filetype: 'media',
|
|
773
|
+
label: 'Source'
|
|
774
|
+
}];
|
|
775
|
+
const sizeInput = !hasDimensions(editor) ? [] : [{
|
|
776
|
+
type: 'sizeinput',
|
|
777
|
+
name: 'dimensions',
|
|
778
|
+
label: 'Constrain proportions',
|
|
779
|
+
constrain: true
|
|
780
|
+
}];
|
|
781
|
+
const generalTab = {
|
|
782
|
+
title: 'General',
|
|
783
|
+
name: 'general',
|
|
784
|
+
items: flatten([
|
|
785
|
+
mediaInput,
|
|
786
|
+
sizeInput
|
|
787
|
+
])
|
|
788
|
+
};
|
|
789
|
+
const embedTextarea = {
|
|
790
|
+
type: 'textarea',
|
|
791
|
+
name: 'embed',
|
|
792
|
+
label: 'Paste your embed code below:'
|
|
793
|
+
};
|
|
794
|
+
const embedTab = {
|
|
795
|
+
title: 'Embed',
|
|
796
|
+
items: [embedTextarea]
|
|
797
|
+
};
|
|
798
|
+
const advancedFormItems = [];
|
|
799
|
+
if (hasAltSource(editor)) {
|
|
800
|
+
advancedFormItems.push({
|
|
801
|
+
name: 'altsource',
|
|
802
|
+
type: 'urlinput',
|
|
803
|
+
filetype: 'media',
|
|
804
|
+
label: 'Alternative source URL'
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
if (hasPoster(editor)) {
|
|
808
|
+
advancedFormItems.push({
|
|
809
|
+
name: 'poster',
|
|
810
|
+
type: 'urlinput',
|
|
811
|
+
filetype: 'image',
|
|
812
|
+
label: 'Media poster (Image URL)'
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
const advancedTab = {
|
|
816
|
+
title: 'Advanced',
|
|
817
|
+
name: 'advanced',
|
|
818
|
+
items: advancedFormItems
|
|
819
|
+
};
|
|
820
|
+
const tabs = [
|
|
821
|
+
generalTab,
|
|
822
|
+
embedTab
|
|
823
|
+
];
|
|
824
|
+
if (advancedFormItems.length > 0) {
|
|
825
|
+
tabs.push(advancedTab);
|
|
826
|
+
}
|
|
827
|
+
const body = {
|
|
828
|
+
type: 'tabpanel',
|
|
829
|
+
tabs
|
|
830
|
+
};
|
|
831
|
+
const win = editor.windowManager.open({
|
|
832
|
+
title: 'Insert/Edit Media',
|
|
833
|
+
size: 'normal',
|
|
834
|
+
body,
|
|
835
|
+
buttons: [
|
|
836
|
+
{
|
|
837
|
+
type: 'cancel',
|
|
838
|
+
name: 'cancel',
|
|
839
|
+
text: 'Cancel'
|
|
840
|
+
},
|
|
841
|
+
{
|
|
842
|
+
type: 'submit',
|
|
843
|
+
name: 'save',
|
|
844
|
+
text: 'Save',
|
|
845
|
+
primary: true
|
|
846
|
+
}
|
|
847
|
+
],
|
|
848
|
+
onSubmit: api => {
|
|
849
|
+
const serviceData = unwrap(api.getData());
|
|
850
|
+
submitForm(currentData.get(), serviceData, editor);
|
|
851
|
+
api.close();
|
|
852
|
+
},
|
|
853
|
+
onChange: (api, detail) => {
|
|
854
|
+
switch (detail.name) {
|
|
855
|
+
case 'source':
|
|
856
|
+
handleSource(currentData.get(), api);
|
|
857
|
+
break;
|
|
858
|
+
case 'embed':
|
|
859
|
+
handleEmbed(api);
|
|
860
|
+
break;
|
|
861
|
+
case 'dimensions':
|
|
862
|
+
case 'altsource':
|
|
863
|
+
case 'poster':
|
|
864
|
+
handleUpdate(api, detail.name);
|
|
865
|
+
break;
|
|
866
|
+
}
|
|
867
|
+
currentData.set(unwrap(api.getData()));
|
|
868
|
+
},
|
|
869
|
+
initialData
|
|
870
|
+
});
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
const get = editor => {
|
|
874
|
+
const showDialog$1 = () => {
|
|
875
|
+
showDialog(editor);
|
|
876
|
+
};
|
|
877
|
+
return { showDialog: showDialog$1 };
|
|
878
|
+
};
|
|
879
|
+
|
|
880
|
+
const register$1 = editor => {
|
|
881
|
+
const showDialog$1 = () => {
|
|
882
|
+
showDialog(editor);
|
|
883
|
+
};
|
|
884
|
+
editor.addCommand('mceMedia', showDialog$1);
|
|
885
|
+
};
|
|
886
|
+
|
|
887
|
+
const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
|
|
888
|
+
const startsWith = (str, prefix) => {
|
|
889
|
+
return checkRange(str, prefix, 0);
|
|
890
|
+
};
|
|
891
|
+
|
|
892
|
+
var global = tinymce.util.Tools.resolve('tinymce.Env');
|
|
893
|
+
|
|
894
|
+
const isLiveEmbedNode = node => {
|
|
895
|
+
const name = node.name;
|
|
896
|
+
return name === 'iframe' || name === 'video' || name === 'audio';
|
|
897
|
+
};
|
|
898
|
+
const getDimension = (node, styles, dimension, defaultValue = null) => {
|
|
899
|
+
const value = node.attr(dimension);
|
|
900
|
+
if (isNonNullable(value)) {
|
|
901
|
+
return value;
|
|
902
|
+
} else if (!has(styles, dimension)) {
|
|
903
|
+
return defaultValue;
|
|
904
|
+
} else {
|
|
905
|
+
return null;
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
const setDimensions = (node, previewNode, styles) => {
|
|
909
|
+
const useDefaults = previewNode.name === 'img' || node.name === 'video';
|
|
910
|
+
const defaultWidth = useDefaults ? '300' : null;
|
|
911
|
+
const fallbackHeight = node.name === 'audio' ? '30' : '150';
|
|
912
|
+
const defaultHeight = useDefaults ? fallbackHeight : null;
|
|
913
|
+
previewNode.attr({
|
|
914
|
+
width: getDimension(node, styles, 'width', defaultWidth),
|
|
915
|
+
height: getDimension(node, styles, 'height', defaultHeight)
|
|
916
|
+
});
|
|
917
|
+
};
|
|
918
|
+
const appendNodeContent = (editor, nodeName, previewNode, html) => {
|
|
919
|
+
const newNode = Parser(editor.schema).parse(html, { context: nodeName });
|
|
920
|
+
while (newNode.firstChild) {
|
|
921
|
+
previewNode.append(newNode.firstChild);
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
const createPlaceholderNode = (editor, node) => {
|
|
925
|
+
const name = node.name;
|
|
926
|
+
const placeHolder = new global$2('img', 1);
|
|
927
|
+
retainAttributesAndInnerHtml(editor, node, placeHolder);
|
|
928
|
+
setDimensions(node, placeHolder, {});
|
|
929
|
+
placeHolder.attr({
|
|
930
|
+
'style': node.attr('style'),
|
|
931
|
+
'src': global.transparentSrc,
|
|
932
|
+
'data-mce-object': name,
|
|
933
|
+
'class': 'mce-object mce-object-' + name
|
|
934
|
+
});
|
|
935
|
+
return placeHolder;
|
|
936
|
+
};
|
|
937
|
+
const createPreviewNode = (editor, node) => {
|
|
938
|
+
const name = node.name;
|
|
939
|
+
const previewWrapper = new global$2('span', 1);
|
|
940
|
+
previewWrapper.attr({
|
|
941
|
+
'contentEditable': 'false',
|
|
942
|
+
'style': node.attr('style'),
|
|
943
|
+
'data-mce-object': name,
|
|
944
|
+
'class': 'mce-preview-object mce-object-' + name
|
|
945
|
+
});
|
|
946
|
+
retainAttributesAndInnerHtml(editor, node, previewWrapper);
|
|
947
|
+
const styles = editor.dom.parseStyle(node.attr('style'));
|
|
948
|
+
const previewNode = new global$2(name, 1);
|
|
949
|
+
setDimensions(node, previewNode, styles);
|
|
950
|
+
previewNode.attr({
|
|
951
|
+
src: node.attr('src'),
|
|
952
|
+
style: node.attr('style'),
|
|
953
|
+
class: node.attr('class')
|
|
954
|
+
});
|
|
955
|
+
if (name === 'iframe') {
|
|
956
|
+
previewNode.attr({
|
|
957
|
+
allowfullscreen: node.attr('allowfullscreen'),
|
|
958
|
+
frameborder: '0'
|
|
959
|
+
});
|
|
960
|
+
} else {
|
|
961
|
+
const attrs = [
|
|
962
|
+
'controls',
|
|
963
|
+
'crossorigin',
|
|
964
|
+
'currentTime',
|
|
965
|
+
'loop',
|
|
966
|
+
'muted',
|
|
967
|
+
'poster',
|
|
968
|
+
'preload'
|
|
969
|
+
];
|
|
970
|
+
each$1(attrs, attrName => {
|
|
971
|
+
previewNode.attr(attrName, node.attr(attrName));
|
|
972
|
+
});
|
|
973
|
+
const sanitizedHtml = previewWrapper.attr('data-mce-html');
|
|
974
|
+
if (isNonNullable(sanitizedHtml)) {
|
|
975
|
+
appendNodeContent(editor, name, previewNode, unescape(sanitizedHtml));
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
const shimNode = new global$2('span', 1);
|
|
979
|
+
shimNode.attr('class', 'mce-shim');
|
|
980
|
+
previewWrapper.append(previewNode);
|
|
981
|
+
previewWrapper.append(shimNode);
|
|
982
|
+
return previewWrapper;
|
|
983
|
+
};
|
|
984
|
+
const retainAttributesAndInnerHtml = (editor, sourceNode, targetNode) => {
|
|
985
|
+
const attribs = sourceNode.attributes;
|
|
986
|
+
let ai = attribs.length;
|
|
987
|
+
while (ai--) {
|
|
988
|
+
const attrName = attribs[ai].name;
|
|
989
|
+
let attrValue = attribs[ai].value;
|
|
990
|
+
if (attrName !== 'width' && attrName !== 'height' && attrName !== 'style' && !startsWith(attrName, 'data-mce-')) {
|
|
991
|
+
if (attrName === 'data' || attrName === 'src') {
|
|
992
|
+
attrValue = editor.convertURL(attrValue, attrName);
|
|
993
|
+
}
|
|
994
|
+
targetNode.attr('data-mce-p-' + attrName, attrValue);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
const serializer = global$1({ inner: true }, editor.schema);
|
|
998
|
+
const tempNode = new global$2('div', 1);
|
|
999
|
+
each$1(sourceNode.children(), child => tempNode.append(child));
|
|
1000
|
+
const innerHtml = serializer.serialize(tempNode);
|
|
1001
|
+
if (innerHtml) {
|
|
1002
|
+
targetNode.attr('data-mce-html', escape(innerHtml));
|
|
1003
|
+
targetNode.empty();
|
|
1004
|
+
}
|
|
1005
|
+
};
|
|
1006
|
+
const isPageEmbedWrapper = node => {
|
|
1007
|
+
const nodeClass = node.attr('class');
|
|
1008
|
+
return nodeClass && /\btiny-pageembed\b/.test(nodeClass);
|
|
1009
|
+
};
|
|
1010
|
+
const isWithinEmbedWrapper = node => {
|
|
1011
|
+
while (node = node.parent) {
|
|
1012
|
+
if (node.attr('data-ephox-embed-iri') || isPageEmbedWrapper(node)) {
|
|
1013
|
+
return true;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
return false;
|
|
1017
|
+
};
|
|
1018
|
+
const placeHolderConverter = editor => nodes => {
|
|
1019
|
+
let i = nodes.length;
|
|
1020
|
+
let node;
|
|
1021
|
+
while (i--) {
|
|
1022
|
+
node = nodes[i];
|
|
1023
|
+
if (!node.parent) {
|
|
1024
|
+
continue;
|
|
1025
|
+
}
|
|
1026
|
+
if (node.parent.attr('data-mce-object')) {
|
|
1027
|
+
continue;
|
|
1028
|
+
}
|
|
1029
|
+
if (isLiveEmbedNode(node) && hasLiveEmbeds(editor)) {
|
|
1030
|
+
if (!isWithinEmbedWrapper(node)) {
|
|
1031
|
+
node.replace(createPreviewNode(editor, node));
|
|
1032
|
+
}
|
|
1033
|
+
} else {
|
|
1034
|
+
if (!isWithinEmbedWrapper(node)) {
|
|
1035
|
+
node.replace(createPlaceholderNode(editor, node));
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
const parseAndSanitize = (editor, context, html) => {
|
|
1042
|
+
const validate = shouldFilterHtml(editor);
|
|
1043
|
+
return Parser(editor.schema, { validate }).parse(html, { context });
|
|
1044
|
+
};
|
|
1045
|
+
|
|
1046
|
+
const setup$1 = editor => {
|
|
1047
|
+
editor.on('PreInit', () => {
|
|
1048
|
+
const {schema, serializer, parser} = editor;
|
|
1049
|
+
const boolAttrs = schema.getBoolAttrs();
|
|
1050
|
+
each$1('webkitallowfullscreen mozallowfullscreen'.split(' '), name => {
|
|
1051
|
+
boolAttrs[name] = {};
|
|
1052
|
+
});
|
|
1053
|
+
each({ embed: ['wmode'] }, (attrs, name) => {
|
|
1054
|
+
const rule = schema.getElementRule(name);
|
|
1055
|
+
each$1(attrs, attr => {
|
|
1056
|
+
rule.attributes[attr] = {};
|
|
1057
|
+
rule.attributesOrder.push(attr);
|
|
1058
|
+
});
|
|
1059
|
+
});
|
|
1060
|
+
parser.addNodeFilter('iframe,video,audio,object,embed,script', placeHolderConverter(editor));
|
|
1061
|
+
serializer.addAttributeFilter('data-mce-object', (nodes, name) => {
|
|
1062
|
+
let i = nodes.length;
|
|
1063
|
+
while (i--) {
|
|
1064
|
+
const node = nodes[i];
|
|
1065
|
+
if (!node.parent) {
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
const realElmName = node.attr(name);
|
|
1069
|
+
const realElm = new global$2(realElmName, 1);
|
|
1070
|
+
if (realElmName !== 'audio' && realElmName !== 'script') {
|
|
1071
|
+
const className = node.attr('class');
|
|
1072
|
+
if (className && className.indexOf('mce-preview-object') !== -1) {
|
|
1073
|
+
realElm.attr({
|
|
1074
|
+
width: node.firstChild.attr('width'),
|
|
1075
|
+
height: node.firstChild.attr('height')
|
|
1076
|
+
});
|
|
1077
|
+
} else {
|
|
1078
|
+
realElm.attr({
|
|
1079
|
+
width: node.attr('width'),
|
|
1080
|
+
height: node.attr('height')
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
realElm.attr({ style: node.attr('style') });
|
|
1085
|
+
const attribs = node.attributes;
|
|
1086
|
+
let ai = attribs.length;
|
|
1087
|
+
while (ai--) {
|
|
1088
|
+
const attrName = attribs[ai].name;
|
|
1089
|
+
if (attrName.indexOf('data-mce-p-') === 0) {
|
|
1090
|
+
realElm.attr(attrName.substr(11), attribs[ai].value);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
if (realElmName === 'script') {
|
|
1094
|
+
realElm.attr('type', 'text/javascript');
|
|
1095
|
+
}
|
|
1096
|
+
const innerHtml = node.attr('data-mce-html');
|
|
1097
|
+
if (innerHtml) {
|
|
1098
|
+
const fragment = parseAndSanitize(editor, realElmName, unescape(innerHtml));
|
|
1099
|
+
each$1(fragment.children(), child => realElm.append(child));
|
|
1100
|
+
}
|
|
1101
|
+
node.replace(realElm);
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
});
|
|
1105
|
+
editor.on('SetContent', () => {
|
|
1106
|
+
const dom = editor.dom;
|
|
1107
|
+
each$1(dom.select('span.mce-preview-object'), elm => {
|
|
1108
|
+
if (dom.select('span.mce-shim', elm).length === 0) {
|
|
1109
|
+
dom.add(elm, 'span', { class: 'mce-shim' });
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
});
|
|
1113
|
+
};
|
|
1114
|
+
|
|
1115
|
+
const setup = editor => {
|
|
1116
|
+
editor.on('ResolveName', e => {
|
|
1117
|
+
let name;
|
|
1118
|
+
if (e.target.nodeType === 1 && (name = e.target.getAttribute('data-mce-object'))) {
|
|
1119
|
+
e.name = name;
|
|
1120
|
+
}
|
|
1121
|
+
});
|
|
1122
|
+
};
|
|
1123
|
+
|
|
1124
|
+
const register = editor => {
|
|
1125
|
+
const onAction = () => editor.execCommand('mceMedia');
|
|
1126
|
+
editor.ui.registry.addToggleButton('media', {
|
|
1127
|
+
tooltip: 'Insert/edit media',
|
|
1128
|
+
icon: 'embed',
|
|
1129
|
+
onAction,
|
|
1130
|
+
onSetup: buttonApi => {
|
|
1131
|
+
const selection = editor.selection;
|
|
1132
|
+
buttonApi.setActive(isMediaElement(selection.getNode()));
|
|
1133
|
+
return selection.selectorChangedWithUnbind('img[data-mce-object],span[data-mce-object],div[data-ephox-embed-iri]', buttonApi.setActive).unbind;
|
|
1134
|
+
}
|
|
1135
|
+
});
|
|
1136
|
+
editor.ui.registry.addMenuItem('media', {
|
|
1137
|
+
icon: 'embed',
|
|
1138
|
+
text: 'Media...',
|
|
1139
|
+
onAction
|
|
1140
|
+
});
|
|
1141
|
+
};
|
|
1142
|
+
|
|
1143
|
+
var Plugin = () => {
|
|
1144
|
+
global$6.add('media', editor => {
|
|
1145
|
+
register$2(editor);
|
|
1146
|
+
register$1(editor);
|
|
1147
|
+
register(editor);
|
|
1148
|
+
setup(editor);
|
|
1149
|
+
setup$1(editor);
|
|
1150
|
+
setup$2(editor);
|
|
1151
|
+
return get(editor);
|
|
1152
|
+
});
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
Plugin();
|
|
1156
|
+
|
|
1157
|
+
})();
|