@ckeditor/ckeditor5-ckbox 36.0.0 → 37.0.0-alpha.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,22 +2,13 @@
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
- /* global document, window, setTimeout, URL */
7
-
8
- /**
9
- * @module ckbox/ckboxcommand
10
- */
11
-
12
5
  import { Command } from 'ckeditor5/src/core';
13
6
  import { createElement, toMap } from 'ckeditor5/src/utils';
14
7
  import { getEnvironmentId, getImageUrls } from './utils';
15
-
16
8
  // Defines the waiting time (in milliseconds) for inserting the chosen asset into the model. The chosen asset is temporarily stored in the
17
9
  // `CKBoxCommand#_chosenAssets` and it is removed from there automatically after this time. See `CKBoxCommand#_chosenAssets` for more
18
10
  // details.
19
11
  const ASSET_INSERTION_WAIT_TIMEOUT = 1000;
20
-
21
12
  /**
22
13
  * The CKBox command. It is used by the {@link module:ckbox/ckboxediting~CKBoxEditing CKBox editing feature} to open the CKBox file manager.
23
14
  * The file manager allows inserting an image or a link to a file into the editor content.
@@ -29,378 +20,294 @@ const ASSET_INSERTION_WAIT_TIMEOUT = 1000;
29
20
  * {@link module:image/image~Image Image feature}.
30
21
  * - To insert links to other files it uses the {@link module:link/linkcommand~LinkCommand 'link'} command from the
31
22
  * {@link module:link/link~Link Link feature}.
32
- *
33
- * @extends module:core/command~Command
34
23
  */
35
24
  export default class CKBoxCommand extends Command {
36
- /**
37
- * @inheritDoc
38
- */
39
- constructor( editor ) {
40
- super( editor );
41
-
42
- /**
43
- * A set of all chosen assets. They are stored temporarily and they are automatically removed 1 second after being chosen.
44
- * Chosen assets have to be "remembered" for a while to be able to map the given asset with the element inserted into the model.
45
- * This association map is then used to set the ID on the model element.
46
- *
47
- * All chosen assets are automatically removed after the timeout, because (theoretically) it may happen that they will never be
48
- * inserted into the model, even if the {@link module:link/linkcommand~LinkCommand `'link'`} command or the
49
- * {@link module:image/image/insertimagecommand~InsertImageCommand `'insertImage'`} command is enabled. Such a case may arise when
50
- * another plugin blocks the command execution. Then, in order not to keep the chosen (but not inserted) assets forever, we delete
51
- * them automatically to prevent memory leakage. The 1 second timeout is enough to insert the asset into the model and extract the
52
- * ID from the chosen asset.
53
- *
54
- * The assets are stored only if
55
- * the {@link module:ckbox/ckbox~CKBoxConfig#ignoreDataId `config.ckbox.ignoreDataId`} option is set to `false` (by default).
56
- *
57
- * @protected
58
- * @member {Set.<module:ckbox/ckbox~CKBoxAssetDefinition>} #_chosenAssets
59
- */
60
- this._chosenAssets = new Set();
61
-
62
- /**
63
- * The DOM element that acts as a mounting point for the CKBox dialog.
64
- *
65
- * @private
66
- * @member {Element|null} #_wrapper
67
- */
68
- this._wrapper = null;
69
-
70
- this._initListeners();
71
- }
72
-
73
- /**
74
- * @inheritDoc
75
- */
76
- refresh() {
77
- this.value = this._getValue();
78
- this.isEnabled = this._checkEnabled();
79
- }
80
-
81
- /**
82
- * @inheritDoc
83
- */
84
- execute() {
85
- this.fire( 'ckbox:open' );
86
- }
87
-
88
- /**
89
- * Indicates if the CKBox dialog is already opened.
90
- *
91
- * @protected
92
- * @returns {Boolean}
93
- */
94
- _getValue() {
95
- return this._wrapper !== null;
96
- }
97
-
98
- /**
99
- * Checks whether the command can be enabled in the current context.
100
- *
101
- * @protected
102
- * @returns {Boolean}
103
- */
104
- _checkEnabled() {
105
- const imageCommand = this.editor.commands.get( 'insertImage' );
106
- const linkCommand = this.editor.commands.get( 'link' );
107
-
108
- if ( !imageCommand.isEnabled && !linkCommand.isEnabled ) {
109
- return false;
110
- }
111
-
112
- return true;
113
- }
114
-
115
- /**
116
- * Creates the options object for the CKBox dialog.
117
- *
118
- * @protected
119
- * @returns {Object} options
120
- * @returns {String} options.theme The theme for CKBox dialog.
121
- * @returns {String} options.language The language for CKBox dialog.
122
- * @returns {String} options.tokenUrl The token endpoint URL.
123
- * @returns {String} options.serviceOrigin The base URL of the API service.
124
- * @returns {String} options.assetsOrigin The base URL for assets inserted into the editor.
125
- * @returns {Object} options.dialog
126
- * @returns {Function} options.dialog.onClose The callback function invoked after closing the CKBox dialog.
127
- * @returns {Object} options.assets
128
- * @returns {Function} options.assets.onChoose The callback function invoked after choosing the assets.
129
- */
130
- _prepareOptions() {
131
- const editor = this.editor;
132
- const ckboxConfig = editor.config.get( 'ckbox' );
133
-
134
- return {
135
- theme: ckboxConfig.theme,
136
- language: ckboxConfig.language,
137
- tokenUrl: ckboxConfig.tokenUrl,
138
- serviceOrigin: ckboxConfig.serviceOrigin,
139
- assetsOrigin: ckboxConfig.assetsOrigin,
140
- dialog: {
141
- onClose: () => this.fire( 'ckbox:close' )
142
- },
143
- assets: {
144
- onChoose: assets => this.fire( 'ckbox:choose', assets )
145
- }
146
- };
147
- }
148
-
149
- /**
150
- * Initializes various event listeners for the `ckbox:*` events, because all functionality of the `ckbox` command is event-based.
151
- *
152
- * @protected
153
- */
154
- _initListeners() {
155
- const editor = this.editor;
156
- const model = editor.model;
157
- const shouldInsertDataId = !editor.config.get( 'ckbox.ignoreDataId' );
158
-
159
- // Refresh the command after firing the `ckbox:*` event.
160
- this.on( 'ckbox', () => {
161
- this.refresh();
162
- }, { priority: 'low' } );
163
-
164
- // Handle opening of the CKBox dialog.
165
- this.on( 'ckbox:open', () => {
166
- if ( !this.isEnabled || this.value ) {
167
- return;
168
- }
169
-
170
- this._wrapper = createElement( document, 'div', { class: 'ck ckbox-wrapper' } );
171
- document.body.appendChild( this._wrapper );
172
-
173
- window.CKBox.mount( this._wrapper, this._prepareOptions() );
174
- } );
175
-
176
- // Handle closing of the CKBox dialog.
177
- this.on( 'ckbox:close', () => {
178
- if ( !this.value ) {
179
- return;
180
- }
181
-
182
- this._wrapper.remove();
183
- this._wrapper = null;
184
- } );
185
-
186
- // Handle choosing the assets.
187
- this.on( 'ckbox:choose', ( evt, assets ) => {
188
- if ( !this.isEnabled ) {
189
- return;
190
- }
191
-
192
- const imageCommand = editor.commands.get( 'insertImage' );
193
- const linkCommand = editor.commands.get( 'link' );
194
- const ckboxEditing = editor.plugins.get( 'CKBoxEditing' );
195
- const assetsOrigin = editor.config.get( 'ckbox.assetsOrigin' );
196
-
197
- const assetsToProcess = prepareAssets( {
198
- assets,
199
- origin: assetsOrigin,
200
- token: ckboxEditing.getToken(),
201
- isImageAllowed: imageCommand.isEnabled,
202
- isLinkAllowed: linkCommand.isEnabled
203
- } );
204
-
205
- if ( assetsToProcess.length === 0 ) {
206
- return;
207
- }
208
-
209
- // All assets are inserted in one undo step.
210
- model.change( writer => {
211
- for ( const asset of assetsToProcess ) {
212
- const isLastAsset = asset === assetsToProcess[ assetsToProcess.length - 1 ];
213
-
214
- this._insertAsset( asset, isLastAsset, writer );
215
-
216
- // If asset ID must be set for the inserted model element, store the asset temporarily and remove it automatically
217
- // after the timeout.
218
- if ( shouldInsertDataId ) {
219
- setTimeout( () => this._chosenAssets.delete( asset ), ASSET_INSERTION_WAIT_TIMEOUT );
220
-
221
- this._chosenAssets.add( asset );
222
- }
223
- }
224
- } );
225
- } );
226
-
227
- // Clean up after the editor is destroyed.
228
- this.listenTo( editor, 'destroy', () => {
229
- this.fire( 'ckbox:close' );
230
- this._chosenAssets.clear();
231
- } );
232
- }
233
-
234
- /**
235
- * Inserts the asset into the model.
236
- *
237
- * @protected
238
- * @param {Object} asset The asset to be inserted.
239
- * @param {Boolean} isLastAsset Indicates if the current asset is the last one from the chosen set.
240
- * @param {module:engine/model/writer~Writer} writer An instance of the model writer.
241
- */
242
- _insertAsset( asset, isLastAsset, writer ) {
243
- const editor = this.editor;
244
- const model = editor.model;
245
- const selection = model.document.selection;
246
-
247
- // Remove the `linkHref` attribute to not affect the asset to be inserted.
248
- writer.removeSelectionAttribute( 'linkHref' );
249
-
250
- if ( asset.type === 'image' ) {
251
- this._insertImage( asset );
252
- } else {
253
- this._insertLink( asset, writer );
254
- }
255
-
256
- // Except for the last chosen asset, move the selection to the end of the current range to avoid overwriting other, already
257
- // inserted assets.
258
- if ( !isLastAsset ) {
259
- writer.setSelection( selection.getLastPosition() );
260
- }
261
- }
262
-
263
- /**
264
- * Inserts the image by calling the `insertImage` command.
265
- *
266
- * @protected
267
- * @param {module:ckbox/ckbox~CKBoxAssetDefinition} asset The asset to be inserted.
268
- */
269
- _insertImage( asset ) {
270
- const editor = this.editor;
271
- const { imageFallbackUrl, imageSources, imageTextAlternative } = asset.attributes;
272
-
273
- editor.execute( 'insertImage', {
274
- source: {
275
- src: imageFallbackUrl,
276
- sources: imageSources,
277
- alt: imageTextAlternative
278
- }
279
- } );
280
- }
281
-
282
- /**
283
- * Inserts the link to the asset by calling the `link` command.
284
- *
285
- * @protected
286
- * @param {module:ckbox/ckbox~CKBoxAssetDefinition} asset The asset to be inserted.
287
- * @param {module:engine/model/writer~Writer} writer An instance of the model writer.
288
- */
289
- _insertLink( asset, writer ) {
290
- const editor = this.editor;
291
- const model = editor.model;
292
- const selection = model.document.selection;
293
- const { linkName, linkHref } = asset.attributes;
294
-
295
- // If the selection is collapsed, insert the asset name as the link label and select it.
296
- if ( selection.isCollapsed ) {
297
- const selectionAttributes = toMap( selection.getAttributes() );
298
- const textNode = writer.createText( linkName, selectionAttributes );
299
- const range = model.insertContent( textNode );
300
-
301
- writer.setSelection( range );
302
- }
303
-
304
- editor.execute( 'link', linkHref );
305
- }
306
- }
307
-
308
- // Parses the chosen assets into the internal data format. Filters out chosen assets that are not allowed.
309
- //
310
- // @private
311
- // @param {Object} data
312
- // @param {Array.<module:ckbox/ckbox~CKBoxRawAssetDefinition>} data.assets
313
- // @param {String} data.origin The base URL for assets inserted into the editor.
314
- // @param {module:cloud-services/token~Token} data.token
315
- // @param {Boolean} data.isImageAllowed
316
- // @param {Boolean} data.isLinkAllowed
317
- // @returns {Array.<module:ckbox/ckbox~CKBoxAssetDefinition>}
318
- function prepareAssets( { assets, origin, token, isImageAllowed, isLinkAllowed } ) {
319
- return assets
320
- .map( asset => ( {
321
- id: asset.data.id,
322
- type: isImage( asset ) ? 'image' : 'link',
323
- attributes: prepareAssetAttributes( asset, token, origin )
324
- } ) )
325
- .filter( asset => asset.type === 'image' ? isImageAllowed : isLinkAllowed );
25
+ /**
26
+ * @inheritDoc
27
+ */
28
+ constructor(editor) {
29
+ super(editor);
30
+ /**
31
+ * A set of all chosen assets. They are stored temporarily and they are automatically removed 1 second after being chosen.
32
+ * Chosen assets have to be "remembered" for a while to be able to map the given asset with the element inserted into the model.
33
+ * This association map is then used to set the ID on the model element.
34
+ *
35
+ * All chosen assets are automatically removed after the timeout, because (theoretically) it may happen that they will never be
36
+ * inserted into the model, even if the {@link module:link/linkcommand~LinkCommand `'link'`} command or the
37
+ * {@link module:image/image/insertimagecommand~InsertImageCommand `'insertImage'`} command is enabled. Such a case may arise when
38
+ * another plugin blocks the command execution. Then, in order not to keep the chosen (but not inserted) assets forever, we delete
39
+ * them automatically to prevent memory leakage. The 1 second timeout is enough to insert the asset into the model and extract the
40
+ * ID from the chosen asset.
41
+ *
42
+ * The assets are stored only if
43
+ * the {@link module:ckbox/ckboxconfig~CKBoxConfig#ignoreDataId `config.ckbox.ignoreDataId`} option is set to `false` (by default).
44
+ *
45
+ * @internal
46
+ */
47
+ this._chosenAssets = new Set();
48
+ /**
49
+ * The DOM element that acts as a mounting point for the CKBox dialog.
50
+ */
51
+ this._wrapper = null;
52
+ this._initListeners();
53
+ }
54
+ /**
55
+ * @inheritDoc
56
+ */
57
+ refresh() {
58
+ this.value = this._getValue();
59
+ this.isEnabled = this._checkEnabled();
60
+ }
61
+ /**
62
+ * @inheritDoc
63
+ */
64
+ execute() {
65
+ this.fire('ckbox:open');
66
+ }
67
+ /**
68
+ * Indicates if the CKBox dialog is already opened.
69
+ *
70
+ * @protected
71
+ * @returns {Boolean}
72
+ */
73
+ _getValue() {
74
+ return this._wrapper !== null;
75
+ }
76
+ /**
77
+ * Checks whether the command can be enabled in the current context.
78
+ */
79
+ _checkEnabled() {
80
+ const imageCommand = this.editor.commands.get('insertImage');
81
+ const linkCommand = this.editor.commands.get('link');
82
+ if (!imageCommand.isEnabled && !linkCommand.isEnabled) {
83
+ return false;
84
+ }
85
+ return true;
86
+ }
87
+ /**
88
+ * Creates the options object for the CKBox dialog.
89
+ *
90
+ * @returns The object with properties:
91
+ * - theme The theme for CKBox dialog.
92
+ * - language The language for CKBox dialog.
93
+ * - tokenUrl The token endpoint URL.
94
+ * - serviceOrigin The base URL of the API service.
95
+ * - assetsOrigin The base URL for assets inserted into the editor.
96
+ * - dialog.onClose The callback function invoked after closing the CKBox dialog.
97
+ * - assets.onChoose The callback function invoked after choosing the assets.
98
+ */
99
+ _prepareOptions() {
100
+ const editor = this.editor;
101
+ const ckboxConfig = editor.config.get('ckbox');
102
+ return {
103
+ theme: ckboxConfig.theme,
104
+ language: ckboxConfig.language,
105
+ tokenUrl: ckboxConfig.tokenUrl,
106
+ serviceOrigin: ckboxConfig.serviceOrigin,
107
+ assetsOrigin: ckboxConfig.assetsOrigin,
108
+ dialog: {
109
+ onClose: () => this.fire('ckbox:close')
110
+ },
111
+ assets: {
112
+ onChoose: (assets) => this.fire('ckbox:choose', assets)
113
+ }
114
+ };
115
+ }
116
+ /**
117
+ * Initializes various event listeners for the `ckbox:*` events, because all functionality of the `ckbox` command is event-based.
118
+ */
119
+ _initListeners() {
120
+ const editor = this.editor;
121
+ const model = editor.model;
122
+ const shouldInsertDataId = !editor.config.get('ckbox.ignoreDataId');
123
+ // Refresh the command after firing the `ckbox:*` event.
124
+ this.on('ckbox', () => {
125
+ this.refresh();
126
+ }, { priority: 'low' });
127
+ // Handle opening of the CKBox dialog.
128
+ this.on('ckbox:open', () => {
129
+ if (!this.isEnabled || this.value) {
130
+ return;
131
+ }
132
+ this._wrapper = createElement(document, 'div', { class: 'ck ckbox-wrapper' });
133
+ document.body.appendChild(this._wrapper);
134
+ window.CKBox.mount(this._wrapper, this._prepareOptions());
135
+ });
136
+ // Handle closing of the CKBox dialog.
137
+ this.on('ckbox:close', () => {
138
+ if (!this.value) {
139
+ return;
140
+ }
141
+ this._wrapper.remove();
142
+ this._wrapper = null;
143
+ });
144
+ // Handle choosing the assets.
145
+ this.on('ckbox:choose', (evt, assets) => {
146
+ if (!this.isEnabled) {
147
+ return;
148
+ }
149
+ const imageCommand = editor.commands.get('insertImage');
150
+ const linkCommand = editor.commands.get('link');
151
+ const ckboxEditing = editor.plugins.get('CKBoxEditing');
152
+ const assetsOrigin = editor.config.get('ckbox.assetsOrigin');
153
+ const assetsToProcess = prepareAssets({
154
+ assets,
155
+ origin: assetsOrigin,
156
+ token: ckboxEditing.getToken(),
157
+ isImageAllowed: imageCommand.isEnabled,
158
+ isLinkAllowed: linkCommand.isEnabled
159
+ });
160
+ if (assetsToProcess.length === 0) {
161
+ return;
162
+ }
163
+ // All assets are inserted in one undo step.
164
+ model.change(writer => {
165
+ for (const asset of assetsToProcess) {
166
+ const isLastAsset = asset === assetsToProcess[assetsToProcess.length - 1];
167
+ this._insertAsset(asset, isLastAsset, writer);
168
+ // If asset ID must be set for the inserted model element, store the asset temporarily and remove it automatically
169
+ // after the timeout.
170
+ if (shouldInsertDataId) {
171
+ setTimeout(() => this._chosenAssets.delete(asset), ASSET_INSERTION_WAIT_TIMEOUT);
172
+ this._chosenAssets.add(asset);
173
+ }
174
+ }
175
+ });
176
+ });
177
+ // Clean up after the editor is destroyed.
178
+ this.listenTo(editor, 'destroy', () => {
179
+ this.fire('ckbox:close');
180
+ this._chosenAssets.clear();
181
+ });
182
+ }
183
+ /**
184
+ * Inserts the asset into the model.
185
+ *
186
+ * @param asset The asset to be inserted.
187
+ * @param isLastAsset Indicates if the current asset is the last one from the chosen set.
188
+ * @param writer An instance of the model writer.
189
+ */
190
+ _insertAsset(asset, isLastAsset, writer) {
191
+ const editor = this.editor;
192
+ const model = editor.model;
193
+ const selection = model.document.selection;
194
+ // Remove the `linkHref` attribute to not affect the asset to be inserted.
195
+ writer.removeSelectionAttribute('linkHref');
196
+ if (asset.type === 'image') {
197
+ this._insertImage(asset);
198
+ }
199
+ else {
200
+ this._insertLink(asset, writer);
201
+ }
202
+ // Except for the last chosen asset, move the selection to the end of the current range to avoid overwriting other, already
203
+ // inserted assets.
204
+ if (!isLastAsset) {
205
+ writer.setSelection(selection.getLastPosition());
206
+ }
207
+ }
208
+ /**
209
+ * Inserts the image by calling the `insertImage` command.
210
+ *
211
+ * @param asset The asset to be inserted.
212
+ */
213
+ _insertImage(asset) {
214
+ const editor = this.editor;
215
+ const { imageFallbackUrl, imageSources, imageTextAlternative } = asset.attributes;
216
+ editor.execute('insertImage', {
217
+ source: {
218
+ src: imageFallbackUrl,
219
+ sources: imageSources,
220
+ alt: imageTextAlternative
221
+ }
222
+ });
223
+ }
224
+ /**
225
+ * Inserts the link to the asset by calling the `link` command.
226
+ *
227
+ * @param asset The asset to be inserted.
228
+ * @param writer An instance of the model writer.
229
+ */
230
+ _insertLink(asset, writer) {
231
+ const editor = this.editor;
232
+ const model = editor.model;
233
+ const selection = model.document.selection;
234
+ const { linkName, linkHref } = asset.attributes;
235
+ // If the selection is collapsed, insert the asset name as the link label and select it.
236
+ if (selection.isCollapsed) {
237
+ const selectionAttributes = toMap(selection.getAttributes());
238
+ const textNode = writer.createText(linkName, selectionAttributes);
239
+ const range = model.insertContent(textNode);
240
+ writer.setSelection(range);
241
+ }
242
+ editor.execute('link', linkHref);
243
+ }
326
244
  }
327
-
328
- // Parses the assets attributes into the internal data format.
329
- //
330
- // @private
331
- // @param {module:ckbox/ckbox~CKBoxRawAssetDefinition} asset
332
- // @param {module:cloud-services/token~Token} token
333
- // @param {String} origin The base URL for assets inserted into the editor.
334
- // @returns {module:ckbox/ckbox~CKBoxAssetImageAttributesDefinition|module:ckbox/ckbox~CKBoxAssetLinkAttributesDefinition}
335
- function prepareAssetAttributes( asset, token, origin ) {
336
- if ( isImage( asset ) ) {
337
- const { imageFallbackUrl, imageSources } = getImageUrls( {
338
- token,
339
- origin,
340
- id: asset.data.id,
341
- width: asset.data.metadata.width,
342
- extension: asset.data.extension
343
- } );
344
-
345
- return {
346
- imageFallbackUrl,
347
- imageSources,
348
- imageTextAlternative: asset.data.metadata.description || ''
349
- };
350
- }
351
-
352
- return {
353
- linkName: asset.data.name,
354
- linkHref: getAssetUrl( asset, token, origin )
355
- };
356
- }
357
-
358
- // Checks whether the asset is an image.
359
- //
360
- // @private
361
- // @param {module:ckbox/ckbox~CKBoxRawAssetDefinition} asset
362
- // @returns {Boolean}
363
- function isImage( asset ) {
364
- const metadata = asset.data.metadata;
365
-
366
- if ( !metadata ) {
367
- return false;
368
- }
369
-
370
- return metadata.width && metadata.height;
371
- }
372
-
373
- // Creates the URL for the asset.
374
- //
375
- // @private
376
- // @param {module:ckbox/ckbox~CKBoxRawAssetDefinition} asset
377
- // @param {module:cloud-services/token~Token} token
378
- // @param {String} origin The base URL for assets inserted into the editor.
379
- // @returns {String}
380
- function getAssetUrl( asset, token, origin ) {
381
- const environmentId = getEnvironmentId( token );
382
- const url = new URL( `${ environmentId }/assets/${ asset.data.id }/file`, origin );
383
-
384
- url.searchParams.set( 'download', 'true' );
385
-
386
- return url.toString();
245
+ /**
246
+ * Parses the chosen assets into the internal data format. Filters out chosen assets that are not allowed.
247
+ */
248
+ function prepareAssets({ assets, origin, token, isImageAllowed, isLinkAllowed }) {
249
+ return assets
250
+ .map(asset => isImage(asset) ?
251
+ {
252
+ id: asset.data.id,
253
+ type: 'image',
254
+ attributes: prepareImageAssetAttributes(asset, token, origin)
255
+ } :
256
+ {
257
+ id: asset.data.id,
258
+ type: 'link',
259
+ attributes: prepareLinkAssetAttributes(asset, token, origin)
260
+ })
261
+ .filter(asset => asset.type === 'image' ? isImageAllowed : isLinkAllowed);
387
262
  }
388
-
389
263
  /**
390
- * Fired when the command is executed.
264
+ * Parses the assets attributes into the internal data format.
391
265
  *
392
- * @event ckbox:open
266
+ * @param origin The base URL for assets inserted into the editor.
393
267
  */
394
-
268
+ function prepareImageAssetAttributes(asset, token, origin) {
269
+ const { imageFallbackUrl, imageSources } = getImageUrls({
270
+ token,
271
+ origin,
272
+ id: asset.data.id,
273
+ width: asset.data.metadata.width,
274
+ extension: asset.data.extension
275
+ });
276
+ return {
277
+ imageFallbackUrl,
278
+ imageSources,
279
+ imageTextAlternative: asset.data.metadata.description || ''
280
+ };
281
+ }
395
282
  /**
396
- * Fired when the CKBox dialog is closed.
283
+ * Parses the assets attributes into the internal data format.
397
284
  *
398
- * @event ckbox:close
285
+ * @param origin The base URL for assets inserted into the editor.
399
286
  */
400
-
287
+ function prepareLinkAssetAttributes(asset, token, origin) {
288
+ return {
289
+ linkName: asset.data.name,
290
+ linkHref: getAssetUrl(asset, token, origin)
291
+ };
292
+ }
401
293
  /**
402
- * Fired after the assets are chosen.
294
+ * Checks whether the asset is an image.
295
+ */
296
+ function isImage(asset) {
297
+ const metadata = asset.data.metadata;
298
+ if (!metadata) {
299
+ return false;
300
+ }
301
+ return metadata.width && metadata.height;
302
+ }
303
+ /**
304
+ * Creates the URL for the asset.
403
305
  *
404
- * @event ckbox:choose
405
- * @param {Array.<module:ckbox/ckbox~CKBoxRawAssetDefinition>} assets Chosen assets.
306
+ * @param origin The base URL for assets inserted into the editor.
406
307
  */
308
+ function getAssetUrl(asset, token, origin) {
309
+ const environmentId = getEnvironmentId(token);
310
+ const url = new URL(`${environmentId}/assets/${asset.data.id}/file`, origin);
311
+ url.searchParams.set('download', 'true');
312
+ return url.toString();
313
+ }