@ckeditor/ckeditor5-media-embed 39.0.1 → 40.0.0
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/LICENSE.md +1 -1
- package/README.md +3 -3
- package/build/media-embed.js.map +1 -0
- package/build/translations/pt-br.js +1 -1
- package/lang/translations/ar.po +1 -0
- package/lang/translations/az.po +1 -0
- package/lang/translations/bg.po +1 -0
- package/lang/translations/bn.po +1 -0
- package/lang/translations/ca.po +1 -0
- package/lang/translations/cs.po +1 -0
- package/lang/translations/da.po +1 -0
- package/lang/translations/de-ch.po +1 -0
- package/lang/translations/de.po +1 -0
- package/lang/translations/el.po +1 -0
- package/lang/translations/en-au.po +1 -0
- package/lang/translations/en-gb.po +1 -0
- package/lang/translations/en.po +1 -0
- package/lang/translations/es.po +1 -0
- package/lang/translations/et.po +1 -0
- package/lang/translations/fa.po +1 -0
- package/lang/translations/fi.po +1 -0
- package/lang/translations/fr.po +1 -0
- package/lang/translations/gl.po +1 -0
- package/lang/translations/he.po +1 -0
- package/lang/translations/hi.po +1 -0
- package/lang/translations/hr.po +1 -0
- package/lang/translations/hu.po +1 -0
- package/lang/translations/id.po +1 -0
- package/lang/translations/it.po +1 -0
- package/lang/translations/ja.po +1 -0
- package/lang/translations/ko.po +1 -0
- package/lang/translations/ku.po +1 -0
- package/lang/translations/lt.po +1 -0
- package/lang/translations/lv.po +1 -0
- package/lang/translations/ms.po +1 -0
- package/lang/translations/ne.po +1 -0
- package/lang/translations/nl.po +1 -0
- package/lang/translations/no.po +1 -0
- package/lang/translations/pl.po +1 -0
- package/lang/translations/pt-br.po +2 -1
- package/lang/translations/pt.po +1 -0
- package/lang/translations/ro.po +1 -0
- package/lang/translations/ru.po +1 -0
- package/lang/translations/sk.po +1 -0
- package/lang/translations/sq.po +1 -0
- package/lang/translations/sr-latn.po +1 -0
- package/lang/translations/sr.po +1 -0
- package/lang/translations/sv.po +1 -0
- package/lang/translations/th.po +1 -0
- package/lang/translations/tk.po +1 -0
- package/lang/translations/tr.po +1 -0
- package/lang/translations/uk.po +1 -0
- package/lang/translations/ur.po +1 -0
- package/lang/translations/uz.po +1 -0
- package/lang/translations/vi.po +1 -0
- package/lang/translations/zh-cn.po +1 -0
- package/lang/translations/zh.po +1 -0
- package/package.json +3 -7
- package/src/augmentation.d.ts +25 -25
- package/src/augmentation.js +5 -5
- package/src/automediaembed.d.ts +51 -51
- package/src/automediaembed.js +131 -131
- package/src/converters.d.ts +38 -38
- package/src/converters.js +53 -53
- package/src/index.d.ts +15 -15
- package/src/index.js +13 -13
- package/src/mediaembed.d.ts +34 -34
- package/src/mediaembed.js +38 -38
- package/src/mediaembedcommand.d.ts +36 -36
- package/src/mediaembedcommand.js +71 -71
- package/src/mediaembedconfig.d.ts +278 -278
- package/src/mediaembedconfig.js +5 -5
- package/src/mediaembedediting.d.ts +31 -31
- package/src/mediaembedediting.js +231 -231
- package/src/mediaembedtoolbar.d.ts +30 -30
- package/src/mediaembedtoolbar.js +44 -44
- package/src/mediaembedui.d.ts +27 -27
- package/src/mediaembedui.js +99 -99
- package/src/mediaregistry.d.ts +66 -66
- package/src/mediaregistry.js +232 -232
- package/src/ui/mediaformview.d.ts +115 -115
- package/src/ui/mediaformview.js +194 -194
- package/src/utils.d.ts +67 -67
- package/src/utils.js +85 -85
- package/theme/icons/media/twitter.svg +0 -0
package/src/mediaembedediting.js
CHANGED
@@ -1,231 +1,231 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
-
*/
|
5
|
-
/**
|
6
|
-
* @module media-embed/mediaembedediting
|
7
|
-
*/
|
8
|
-
import { Plugin } from 'ckeditor5/src/core';
|
9
|
-
import { first } from 'ckeditor5/src/utils';
|
10
|
-
import { modelToViewUrlAttributeConverter } from './converters';
|
11
|
-
import MediaEmbedCommand from './mediaembedcommand';
|
12
|
-
import MediaRegistry from './mediaregistry';
|
13
|
-
import { toMediaWidget, createMediaFigureElement } from './utils';
|
14
|
-
import '../theme/mediaembedediting.css';
|
15
|
-
/**
|
16
|
-
* The media embed editing feature.
|
17
|
-
*/
|
18
|
-
export default class MediaEmbedEditing extends Plugin {
|
19
|
-
/**
|
20
|
-
* @inheritDoc
|
21
|
-
*/
|
22
|
-
static get pluginName() {
|
23
|
-
return 'MediaEmbedEditing';
|
24
|
-
}
|
25
|
-
/**
|
26
|
-
* @inheritDoc
|
27
|
-
*/
|
28
|
-
constructor(editor) {
|
29
|
-
super(editor);
|
30
|
-
editor.config.define('mediaEmbed', {
|
31
|
-
elementName: 'oembed',
|
32
|
-
providers: [
|
33
|
-
{
|
34
|
-
name: 'dailymotion',
|
35
|
-
url: /^dailymotion\.com\/video\/(\w+)/,
|
36
|
-
html: match => {
|
37
|
-
const id = match[1];
|
38
|
-
return ('<div style="position: relative; padding-bottom: 100%; height: 0; ">' +
|
39
|
-
`<iframe src="https://www.dailymotion.com/embed/video/${id}" ` +
|
40
|
-
'style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;" ' +
|
41
|
-
'frameborder="0" width="480" height="270" allowfullscreen allow="autoplay">' +
|
42
|
-
'</iframe>' +
|
43
|
-
'</div>');
|
44
|
-
}
|
45
|
-
},
|
46
|
-
{
|
47
|
-
name: 'spotify',
|
48
|
-
url: [
|
49
|
-
/^open\.spotify\.com\/(artist\/\w+)/,
|
50
|
-
/^open\.spotify\.com\/(album\/\w+)/,
|
51
|
-
/^open\.spotify\.com\/(track\/\w+)/
|
52
|
-
],
|
53
|
-
html: match => {
|
54
|
-
const id = match[1];
|
55
|
-
return ('<div style="position: relative; padding-bottom: 100%; height: 0; padding-bottom: 126%;">' +
|
56
|
-
`<iframe src="https://open.spotify.com/embed/${id}" ` +
|
57
|
-
'style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;" ' +
|
58
|
-
'frameborder="0" allowtransparency="true" allow="encrypted-media">' +
|
59
|
-
'</iframe>' +
|
60
|
-
'</div>');
|
61
|
-
}
|
62
|
-
},
|
63
|
-
{
|
64
|
-
name: 'youtube',
|
65
|
-
url: [
|
66
|
-
/^(?:m\.)?youtube\.com\/watch\?v=([\w-]+)(?:&t=(\d+))?/,
|
67
|
-
/^(?:m\.)?youtube\.com\/v\/([\w-]+)(?:\?t=(\d+))?/,
|
68
|
-
/^youtube\.com\/embed\/([\w-]+)(?:\?start=(\d+))?/,
|
69
|
-
/^youtu\.be\/([\w-]+)(?:\?t=(\d+))?/
|
70
|
-
],
|
71
|
-
html: match => {
|
72
|
-
const id = match[1];
|
73
|
-
const time = match[2];
|
74
|
-
return ('<div style="position: relative; padding-bottom: 100%; height: 0; padding-bottom: 56.2493%;">' +
|
75
|
-
`<iframe src="https://www.youtube.com/embed/${id}${time ? `?start=${time}` : ''}" ` +
|
76
|
-
'style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;" ' +
|
77
|
-
'frameborder="0" allow="autoplay; encrypted-media" allowfullscreen>' +
|
78
|
-
'</iframe>' +
|
79
|
-
'</div>');
|
80
|
-
}
|
81
|
-
},
|
82
|
-
{
|
83
|
-
name: 'vimeo',
|
84
|
-
url: [
|
85
|
-
/^vimeo\.com\/(\d+)/,
|
86
|
-
/^vimeo\.com\/[^/]+\/[^/]+\/video\/(\d+)/,
|
87
|
-
/^vimeo\.com\/album\/[^/]+\/video\/(\d+)/,
|
88
|
-
/^vimeo\.com\/channels\/[^/]+\/(\d+)/,
|
89
|
-
/^vimeo\.com\/groups\/[^/]+\/videos\/(\d+)/,
|
90
|
-
/^vimeo\.com\/ondemand\/[^/]+\/(\d+)/,
|
91
|
-
/^player\.vimeo\.com\/video\/(\d+)/
|
92
|
-
],
|
93
|
-
html: match => {
|
94
|
-
const id = match[1];
|
95
|
-
return ('<div style="position: relative; padding-bottom: 100%; height: 0; padding-bottom: 56.2493%;">' +
|
96
|
-
`<iframe src="https://player.vimeo.com/video/${id}" ` +
|
97
|
-
'style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;" ' +
|
98
|
-
'frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen>' +
|
99
|
-
'</iframe>' +
|
100
|
-
'</div>');
|
101
|
-
}
|
102
|
-
},
|
103
|
-
{
|
104
|
-
name: 'instagram',
|
105
|
-
url: /^instagram\.com\/p\/(\w+)/
|
106
|
-
},
|
107
|
-
{
|
108
|
-
name: 'twitter',
|
109
|
-
url: /^twitter\.com/
|
110
|
-
},
|
111
|
-
{
|
112
|
-
name: 'googleMaps',
|
113
|
-
url: [
|
114
|
-
/^google\.com\/maps/,
|
115
|
-
/^goo\.gl\/maps/,
|
116
|
-
/^maps\.google\.com/,
|
117
|
-
/^maps\.app\.goo\.gl/
|
118
|
-
]
|
119
|
-
},
|
120
|
-
{
|
121
|
-
name: 'flickr',
|
122
|
-
url: /^flickr\.com/
|
123
|
-
},
|
124
|
-
{
|
125
|
-
name: 'facebook',
|
126
|
-
url: /^facebook\.com/
|
127
|
-
}
|
128
|
-
]
|
129
|
-
});
|
130
|
-
this.registry = new MediaRegistry(editor.locale, editor.config.get('mediaEmbed'));
|
131
|
-
}
|
132
|
-
/**
|
133
|
-
* @inheritDoc
|
134
|
-
*/
|
135
|
-
init() {
|
136
|
-
const editor = this.editor;
|
137
|
-
const schema = editor.model.schema;
|
138
|
-
const t = editor.t;
|
139
|
-
const conversion = editor.conversion;
|
140
|
-
const renderMediaPreview = editor.config.get('mediaEmbed.previewsInData');
|
141
|
-
const elementName = editor.config.get('mediaEmbed.elementName');
|
142
|
-
const registry = this.registry;
|
143
|
-
editor.commands.add('mediaEmbed', new MediaEmbedCommand(editor));
|
144
|
-
// Configure the schema.
|
145
|
-
schema.register('media', {
|
146
|
-
inheritAllFrom: '$blockObject',
|
147
|
-
allowAttributes: ['url']
|
148
|
-
});
|
149
|
-
// Model -> Data
|
150
|
-
conversion.for('dataDowncast').elementToStructure({
|
151
|
-
model: 'media',
|
152
|
-
view: (modelElement, { writer }) => {
|
153
|
-
const url = modelElement.getAttribute('url');
|
154
|
-
return createMediaFigureElement(writer, registry, url, {
|
155
|
-
elementName,
|
156
|
-
renderMediaPreview: !!url && renderMediaPreview
|
157
|
-
});
|
158
|
-
}
|
159
|
-
});
|
160
|
-
// Model -> Data (url -> data-oembed-url)
|
161
|
-
conversion.for('dataDowncast').add(modelToViewUrlAttributeConverter(registry, {
|
162
|
-
elementName,
|
163
|
-
renderMediaPreview
|
164
|
-
}));
|
165
|
-
// Model -> View (element)
|
166
|
-
conversion.for('editingDowncast').elementToStructure({
|
167
|
-
model: 'media',
|
168
|
-
view: (modelElement, { writer }) => {
|
169
|
-
const url = modelElement.getAttribute('url');
|
170
|
-
const figure = createMediaFigureElement(writer, registry, url, {
|
171
|
-
elementName,
|
172
|
-
renderForEditingView: true
|
173
|
-
});
|
174
|
-
return toMediaWidget(figure, writer, t('media widget'));
|
175
|
-
}
|
176
|
-
});
|
177
|
-
// Model -> View (url -> data-oembed-url)
|
178
|
-
conversion.for('editingDowncast').add(modelToViewUrlAttributeConverter(registry, {
|
179
|
-
elementName,
|
180
|
-
renderForEditingView: true
|
181
|
-
}));
|
182
|
-
// View -> Model (data-oembed-url -> url)
|
183
|
-
conversion.for('upcast')
|
184
|
-
// Upcast semantic media.
|
185
|
-
.elementToElement({
|
186
|
-
view: element => ['oembed', elementName].includes(element.name) && element.getAttribute('url') ?
|
187
|
-
{ name: true } :
|
188
|
-
null,
|
189
|
-
model: (viewMedia, { writer }) => {
|
190
|
-
const url = viewMedia.getAttribute('url');
|
191
|
-
if (registry.hasMedia(url)) {
|
192
|
-
return writer.createElement('media', { url });
|
193
|
-
}
|
194
|
-
return null;
|
195
|
-
}
|
196
|
-
})
|
197
|
-
// Upcast non-semantic media.
|
198
|
-
.elementToElement({
|
199
|
-
view: {
|
200
|
-
name: 'div',
|
201
|
-
attributes: {
|
202
|
-
'data-oembed-url': true
|
203
|
-
}
|
204
|
-
},
|
205
|
-
model: (viewMedia, { writer }) => {
|
206
|
-
const url = viewMedia.getAttribute('data-oembed-url');
|
207
|
-
if (registry.hasMedia(url)) {
|
208
|
-
return writer.createElement('media', { url });
|
209
|
-
}
|
210
|
-
return null;
|
211
|
-
}
|
212
|
-
})
|
213
|
-
// Consume `<figure class="media">` elements, that were left after upcast.
|
214
|
-
.add(dispatcher => {
|
215
|
-
const converter = (evt, data, conversionApi) => {
|
216
|
-
if (!conversionApi.consumable.consume(data.viewItem, { name: true, classes: 'media' })) {
|
217
|
-
return;
|
218
|
-
}
|
219
|
-
const { modelRange, modelCursor } = conversionApi.convertChildren(data.viewItem, data.modelCursor);
|
220
|
-
data.modelRange = modelRange;
|
221
|
-
data.modelCursor = modelCursor;
|
222
|
-
const modelElement = first(modelRange.getItems());
|
223
|
-
if (!modelElement) {
|
224
|
-
// Revert consumed figure so other features can convert it.
|
225
|
-
conversionApi.consumable.revert(data.viewItem, { name: true, classes: 'media' });
|
226
|
-
}
|
227
|
-
};
|
228
|
-
dispatcher.on('element:figure', converter);
|
229
|
-
});
|
230
|
-
}
|
231
|
-
}
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module media-embed/mediaembedediting
|
7
|
+
*/
|
8
|
+
import { Plugin } from 'ckeditor5/src/core';
|
9
|
+
import { first } from 'ckeditor5/src/utils';
|
10
|
+
import { modelToViewUrlAttributeConverter } from './converters';
|
11
|
+
import MediaEmbedCommand from './mediaembedcommand';
|
12
|
+
import MediaRegistry from './mediaregistry';
|
13
|
+
import { toMediaWidget, createMediaFigureElement } from './utils';
|
14
|
+
import '../theme/mediaembedediting.css';
|
15
|
+
/**
|
16
|
+
* The media embed editing feature.
|
17
|
+
*/
|
18
|
+
export default class MediaEmbedEditing extends Plugin {
|
19
|
+
/**
|
20
|
+
* @inheritDoc
|
21
|
+
*/
|
22
|
+
static get pluginName() {
|
23
|
+
return 'MediaEmbedEditing';
|
24
|
+
}
|
25
|
+
/**
|
26
|
+
* @inheritDoc
|
27
|
+
*/
|
28
|
+
constructor(editor) {
|
29
|
+
super(editor);
|
30
|
+
editor.config.define('mediaEmbed', {
|
31
|
+
elementName: 'oembed',
|
32
|
+
providers: [
|
33
|
+
{
|
34
|
+
name: 'dailymotion',
|
35
|
+
url: /^dailymotion\.com\/video\/(\w+)/,
|
36
|
+
html: match => {
|
37
|
+
const id = match[1];
|
38
|
+
return ('<div style="position: relative; padding-bottom: 100%; height: 0; ">' +
|
39
|
+
`<iframe src="https://www.dailymotion.com/embed/video/${id}" ` +
|
40
|
+
'style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;" ' +
|
41
|
+
'frameborder="0" width="480" height="270" allowfullscreen allow="autoplay">' +
|
42
|
+
'</iframe>' +
|
43
|
+
'</div>');
|
44
|
+
}
|
45
|
+
},
|
46
|
+
{
|
47
|
+
name: 'spotify',
|
48
|
+
url: [
|
49
|
+
/^open\.spotify\.com\/(artist\/\w+)/,
|
50
|
+
/^open\.spotify\.com\/(album\/\w+)/,
|
51
|
+
/^open\.spotify\.com\/(track\/\w+)/
|
52
|
+
],
|
53
|
+
html: match => {
|
54
|
+
const id = match[1];
|
55
|
+
return ('<div style="position: relative; padding-bottom: 100%; height: 0; padding-bottom: 126%;">' +
|
56
|
+
`<iframe src="https://open.spotify.com/embed/${id}" ` +
|
57
|
+
'style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;" ' +
|
58
|
+
'frameborder="0" allowtransparency="true" allow="encrypted-media">' +
|
59
|
+
'</iframe>' +
|
60
|
+
'</div>');
|
61
|
+
}
|
62
|
+
},
|
63
|
+
{
|
64
|
+
name: 'youtube',
|
65
|
+
url: [
|
66
|
+
/^(?:m\.)?youtube\.com\/watch\?v=([\w-]+)(?:&t=(\d+))?/,
|
67
|
+
/^(?:m\.)?youtube\.com\/v\/([\w-]+)(?:\?t=(\d+))?/,
|
68
|
+
/^youtube\.com\/embed\/([\w-]+)(?:\?start=(\d+))?/,
|
69
|
+
/^youtu\.be\/([\w-]+)(?:\?t=(\d+))?/
|
70
|
+
],
|
71
|
+
html: match => {
|
72
|
+
const id = match[1];
|
73
|
+
const time = match[2];
|
74
|
+
return ('<div style="position: relative; padding-bottom: 100%; height: 0; padding-bottom: 56.2493%;">' +
|
75
|
+
`<iframe src="https://www.youtube.com/embed/${id}${time ? `?start=${time}` : ''}" ` +
|
76
|
+
'style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;" ' +
|
77
|
+
'frameborder="0" allow="autoplay; encrypted-media" allowfullscreen>' +
|
78
|
+
'</iframe>' +
|
79
|
+
'</div>');
|
80
|
+
}
|
81
|
+
},
|
82
|
+
{
|
83
|
+
name: 'vimeo',
|
84
|
+
url: [
|
85
|
+
/^vimeo\.com\/(\d+)/,
|
86
|
+
/^vimeo\.com\/[^/]+\/[^/]+\/video\/(\d+)/,
|
87
|
+
/^vimeo\.com\/album\/[^/]+\/video\/(\d+)/,
|
88
|
+
/^vimeo\.com\/channels\/[^/]+\/(\d+)/,
|
89
|
+
/^vimeo\.com\/groups\/[^/]+\/videos\/(\d+)/,
|
90
|
+
/^vimeo\.com\/ondemand\/[^/]+\/(\d+)/,
|
91
|
+
/^player\.vimeo\.com\/video\/(\d+)/
|
92
|
+
],
|
93
|
+
html: match => {
|
94
|
+
const id = match[1];
|
95
|
+
return ('<div style="position: relative; padding-bottom: 100%; height: 0; padding-bottom: 56.2493%;">' +
|
96
|
+
`<iframe src="https://player.vimeo.com/video/${id}" ` +
|
97
|
+
'style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;" ' +
|
98
|
+
'frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen>' +
|
99
|
+
'</iframe>' +
|
100
|
+
'</div>');
|
101
|
+
}
|
102
|
+
},
|
103
|
+
{
|
104
|
+
name: 'instagram',
|
105
|
+
url: /^instagram\.com\/p\/(\w+)/
|
106
|
+
},
|
107
|
+
{
|
108
|
+
name: 'twitter',
|
109
|
+
url: /^twitter\.com/
|
110
|
+
},
|
111
|
+
{
|
112
|
+
name: 'googleMaps',
|
113
|
+
url: [
|
114
|
+
/^google\.com\/maps/,
|
115
|
+
/^goo\.gl\/maps/,
|
116
|
+
/^maps\.google\.com/,
|
117
|
+
/^maps\.app\.goo\.gl/
|
118
|
+
]
|
119
|
+
},
|
120
|
+
{
|
121
|
+
name: 'flickr',
|
122
|
+
url: /^flickr\.com/
|
123
|
+
},
|
124
|
+
{
|
125
|
+
name: 'facebook',
|
126
|
+
url: /^facebook\.com/
|
127
|
+
}
|
128
|
+
]
|
129
|
+
});
|
130
|
+
this.registry = new MediaRegistry(editor.locale, editor.config.get('mediaEmbed'));
|
131
|
+
}
|
132
|
+
/**
|
133
|
+
* @inheritDoc
|
134
|
+
*/
|
135
|
+
init() {
|
136
|
+
const editor = this.editor;
|
137
|
+
const schema = editor.model.schema;
|
138
|
+
const t = editor.t;
|
139
|
+
const conversion = editor.conversion;
|
140
|
+
const renderMediaPreview = editor.config.get('mediaEmbed.previewsInData');
|
141
|
+
const elementName = editor.config.get('mediaEmbed.elementName');
|
142
|
+
const registry = this.registry;
|
143
|
+
editor.commands.add('mediaEmbed', new MediaEmbedCommand(editor));
|
144
|
+
// Configure the schema.
|
145
|
+
schema.register('media', {
|
146
|
+
inheritAllFrom: '$blockObject',
|
147
|
+
allowAttributes: ['url']
|
148
|
+
});
|
149
|
+
// Model -> Data
|
150
|
+
conversion.for('dataDowncast').elementToStructure({
|
151
|
+
model: 'media',
|
152
|
+
view: (modelElement, { writer }) => {
|
153
|
+
const url = modelElement.getAttribute('url');
|
154
|
+
return createMediaFigureElement(writer, registry, url, {
|
155
|
+
elementName,
|
156
|
+
renderMediaPreview: !!url && renderMediaPreview
|
157
|
+
});
|
158
|
+
}
|
159
|
+
});
|
160
|
+
// Model -> Data (url -> data-oembed-url)
|
161
|
+
conversion.for('dataDowncast').add(modelToViewUrlAttributeConverter(registry, {
|
162
|
+
elementName,
|
163
|
+
renderMediaPreview
|
164
|
+
}));
|
165
|
+
// Model -> View (element)
|
166
|
+
conversion.for('editingDowncast').elementToStructure({
|
167
|
+
model: 'media',
|
168
|
+
view: (modelElement, { writer }) => {
|
169
|
+
const url = modelElement.getAttribute('url');
|
170
|
+
const figure = createMediaFigureElement(writer, registry, url, {
|
171
|
+
elementName,
|
172
|
+
renderForEditingView: true
|
173
|
+
});
|
174
|
+
return toMediaWidget(figure, writer, t('media widget'));
|
175
|
+
}
|
176
|
+
});
|
177
|
+
// Model -> View (url -> data-oembed-url)
|
178
|
+
conversion.for('editingDowncast').add(modelToViewUrlAttributeConverter(registry, {
|
179
|
+
elementName,
|
180
|
+
renderForEditingView: true
|
181
|
+
}));
|
182
|
+
// View -> Model (data-oembed-url -> url)
|
183
|
+
conversion.for('upcast')
|
184
|
+
// Upcast semantic media.
|
185
|
+
.elementToElement({
|
186
|
+
view: element => ['oembed', elementName].includes(element.name) && element.getAttribute('url') ?
|
187
|
+
{ name: true } :
|
188
|
+
null,
|
189
|
+
model: (viewMedia, { writer }) => {
|
190
|
+
const url = viewMedia.getAttribute('url');
|
191
|
+
if (registry.hasMedia(url)) {
|
192
|
+
return writer.createElement('media', { url });
|
193
|
+
}
|
194
|
+
return null;
|
195
|
+
}
|
196
|
+
})
|
197
|
+
// Upcast non-semantic media.
|
198
|
+
.elementToElement({
|
199
|
+
view: {
|
200
|
+
name: 'div',
|
201
|
+
attributes: {
|
202
|
+
'data-oembed-url': true
|
203
|
+
}
|
204
|
+
},
|
205
|
+
model: (viewMedia, { writer }) => {
|
206
|
+
const url = viewMedia.getAttribute('data-oembed-url');
|
207
|
+
if (registry.hasMedia(url)) {
|
208
|
+
return writer.createElement('media', { url });
|
209
|
+
}
|
210
|
+
return null;
|
211
|
+
}
|
212
|
+
})
|
213
|
+
// Consume `<figure class="media">` elements, that were left after upcast.
|
214
|
+
.add(dispatcher => {
|
215
|
+
const converter = (evt, data, conversionApi) => {
|
216
|
+
if (!conversionApi.consumable.consume(data.viewItem, { name: true, classes: 'media' })) {
|
217
|
+
return;
|
218
|
+
}
|
219
|
+
const { modelRange, modelCursor } = conversionApi.convertChildren(data.viewItem, data.modelCursor);
|
220
|
+
data.modelRange = modelRange;
|
221
|
+
data.modelCursor = modelCursor;
|
222
|
+
const modelElement = first(modelRange.getItems());
|
223
|
+
if (!modelElement) {
|
224
|
+
// Revert consumed figure so other features can convert it.
|
225
|
+
conversionApi.consumable.revert(data.viewItem, { name: true, classes: 'media' });
|
226
|
+
}
|
227
|
+
};
|
228
|
+
dispatcher.on('element:figure', converter);
|
229
|
+
});
|
230
|
+
}
|
231
|
+
}
|
@@ -1,30 +1,30 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
-
*/
|
5
|
-
/**
|
6
|
-
* @module media-embed/mediaembedtoolbar
|
7
|
-
*/
|
8
|
-
import { Plugin } from 'ckeditor5/src/core';
|
9
|
-
import { WidgetToolbarRepository } from 'ckeditor5/src/widget';
|
10
|
-
import './mediaembedconfig';
|
11
|
-
/**
|
12
|
-
* The media embed toolbar plugin. It creates a toolbar for media embed that shows up when the media element is selected.
|
13
|
-
*
|
14
|
-
* Instances of toolbar components (e.g. buttons) are created based on the
|
15
|
-
* {@link module:media-embed/mediaembedconfig~MediaEmbedConfig#toolbar `media.toolbar` configuration option}.
|
16
|
-
*/
|
17
|
-
export default class MediaEmbedToolbar extends Plugin {
|
18
|
-
/**
|
19
|
-
* @inheritDoc
|
20
|
-
*/
|
21
|
-
static get requires(): readonly [typeof WidgetToolbarRepository];
|
22
|
-
/**
|
23
|
-
* @inheritDoc
|
24
|
-
*/
|
25
|
-
static get pluginName(): "MediaEmbedToolbar";
|
26
|
-
/**
|
27
|
-
* @inheritDoc
|
28
|
-
*/
|
29
|
-
afterInit(): void;
|
30
|
-
}
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module media-embed/mediaembedtoolbar
|
7
|
+
*/
|
8
|
+
import { Plugin } from 'ckeditor5/src/core';
|
9
|
+
import { WidgetToolbarRepository } from 'ckeditor5/src/widget';
|
10
|
+
import './mediaembedconfig';
|
11
|
+
/**
|
12
|
+
* The media embed toolbar plugin. It creates a toolbar for media embed that shows up when the media element is selected.
|
13
|
+
*
|
14
|
+
* Instances of toolbar components (e.g. buttons) are created based on the
|
15
|
+
* {@link module:media-embed/mediaembedconfig~MediaEmbedConfig#toolbar `media.toolbar` configuration option}.
|
16
|
+
*/
|
17
|
+
export default class MediaEmbedToolbar extends Plugin {
|
18
|
+
/**
|
19
|
+
* @inheritDoc
|
20
|
+
*/
|
21
|
+
static get requires(): readonly [typeof WidgetToolbarRepository];
|
22
|
+
/**
|
23
|
+
* @inheritDoc
|
24
|
+
*/
|
25
|
+
static get pluginName(): "MediaEmbedToolbar";
|
26
|
+
/**
|
27
|
+
* @inheritDoc
|
28
|
+
*/
|
29
|
+
afterInit(): void;
|
30
|
+
}
|
package/src/mediaembedtoolbar.js
CHANGED
@@ -1,44 +1,44 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
-
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
-
*/
|
5
|
-
/**
|
6
|
-
* @module media-embed/mediaembedtoolbar
|
7
|
-
*/
|
8
|
-
import { Plugin } from 'ckeditor5/src/core';
|
9
|
-
import { WidgetToolbarRepository } from 'ckeditor5/src/widget';
|
10
|
-
import { getSelectedMediaViewWidget } from './utils';
|
11
|
-
import './mediaembedconfig';
|
12
|
-
/**
|
13
|
-
* The media embed toolbar plugin. It creates a toolbar for media embed that shows up when the media element is selected.
|
14
|
-
*
|
15
|
-
* Instances of toolbar components (e.g. buttons) are created based on the
|
16
|
-
* {@link module:media-embed/mediaembedconfig~MediaEmbedConfig#toolbar `media.toolbar` configuration option}.
|
17
|
-
*/
|
18
|
-
export default class MediaEmbedToolbar extends Plugin {
|
19
|
-
/**
|
20
|
-
* @inheritDoc
|
21
|
-
*/
|
22
|
-
static get requires() {
|
23
|
-
return [WidgetToolbarRepository];
|
24
|
-
}
|
25
|
-
/**
|
26
|
-
* @inheritDoc
|
27
|
-
*/
|
28
|
-
static get pluginName() {
|
29
|
-
return 'MediaEmbedToolbar';
|
30
|
-
}
|
31
|
-
/**
|
32
|
-
* @inheritDoc
|
33
|
-
*/
|
34
|
-
afterInit() {
|
35
|
-
const editor = this.editor;
|
36
|
-
const t = editor.t;
|
37
|
-
const widgetToolbarRepository = editor.plugins.get(WidgetToolbarRepository);
|
38
|
-
widgetToolbarRepository.register('mediaEmbed', {
|
39
|
-
ariaLabel: t('Media toolbar'),
|
40
|
-
items: editor.config.get('mediaEmbed.toolbar') || [],
|
41
|
-
getRelatedElement: getSelectedMediaViewWidget
|
42
|
-
});
|
43
|
-
}
|
44
|
-
}
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module media-embed/mediaembedtoolbar
|
7
|
+
*/
|
8
|
+
import { Plugin } from 'ckeditor5/src/core';
|
9
|
+
import { WidgetToolbarRepository } from 'ckeditor5/src/widget';
|
10
|
+
import { getSelectedMediaViewWidget } from './utils';
|
11
|
+
import './mediaembedconfig';
|
12
|
+
/**
|
13
|
+
* The media embed toolbar plugin. It creates a toolbar for media embed that shows up when the media element is selected.
|
14
|
+
*
|
15
|
+
* Instances of toolbar components (e.g. buttons) are created based on the
|
16
|
+
* {@link module:media-embed/mediaembedconfig~MediaEmbedConfig#toolbar `media.toolbar` configuration option}.
|
17
|
+
*/
|
18
|
+
export default class MediaEmbedToolbar extends Plugin {
|
19
|
+
/**
|
20
|
+
* @inheritDoc
|
21
|
+
*/
|
22
|
+
static get requires() {
|
23
|
+
return [WidgetToolbarRepository];
|
24
|
+
}
|
25
|
+
/**
|
26
|
+
* @inheritDoc
|
27
|
+
*/
|
28
|
+
static get pluginName() {
|
29
|
+
return 'MediaEmbedToolbar';
|
30
|
+
}
|
31
|
+
/**
|
32
|
+
* @inheritDoc
|
33
|
+
*/
|
34
|
+
afterInit() {
|
35
|
+
const editor = this.editor;
|
36
|
+
const t = editor.t;
|
37
|
+
const widgetToolbarRepository = editor.plugins.get(WidgetToolbarRepository);
|
38
|
+
widgetToolbarRepository.register('mediaEmbed', {
|
39
|
+
ariaLabel: t('Media toolbar'),
|
40
|
+
items: editor.config.get('mediaEmbed.toolbar') || [],
|
41
|
+
getRelatedElement: getSelectedMediaViewWidget
|
42
|
+
});
|
43
|
+
}
|
44
|
+
}
|