-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
utils.ts
128 lines (113 loc) · 3.68 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
/**
* @module media-embed/utils
*/
import type {
ViewContainerElement,
Element,
Model,
Selectable,
Selection,
DowncastWriter,
ViewDocumentSelection,
ViewElement,
DocumentSelection
} from 'ckeditor5/src/engine.js';
import { isWidget, toWidget } from 'ckeditor5/src/widget.js';
import type MediaRegistry from './mediaregistry.js';
/**
* Converts a given {@link module:engine/view/element~Element} to a media embed widget:
* * Adds a {@link module:engine/view/element~Element#_setCustomProperty custom property} allowing to recognize the media widget element.
* * Calls the {@link module:widget/utils~toWidget} function with the proper element's label creator.
*
* @param writer An instance of the view writer.
* @param label The element's label.
*/
export function toMediaWidget( viewElement: ViewElement, writer: DowncastWriter, label: string ): ViewElement {
writer.setCustomProperty( 'media', true, viewElement );
return toWidget( viewElement, writer, { label } );
}
/**
* Returns a media widget editing view element if one is selected.
*/
export function getSelectedMediaViewWidget( selection: ViewDocumentSelection ): ViewElement | null {
const viewElement = selection.getSelectedElement();
if ( viewElement && isMediaWidget( viewElement ) ) {
return viewElement;
}
return null;
}
/**
* Checks if a given view element is a media widget.
*/
export function isMediaWidget( viewElement: ViewElement ): boolean {
return !!viewElement.getCustomProperty( 'media' ) && isWidget( viewElement );
}
/**
* Creates a view element representing the media. Either a "semantic" one for the data pipeline:
*
* ```html
* <figure class="media">
* <oembed url="foo"></oembed>
* </figure>
* ```
*
* or a "non-semantic" (for the editing view pipeline):
*
* ```html
* <figure class="media">
* <div data-oembed-url="foo">[ non-semantic media preview for "foo" ]</div>
* </figure>
* ```
*/
export function createMediaFigureElement(
writer: DowncastWriter,
registry: MediaRegistry,
url: string,
options: MediaOptions
): ViewContainerElement {
return writer.createContainerElement( 'figure', { class: 'media' }, [
registry.getMediaViewElement( writer, url, options ),
writer.createSlot()
] );
}
/**
* Returns a selected media element in the model, if any.
*/
export function getSelectedMediaModelWidget( selection: Selection | DocumentSelection ): Element | null {
const selectedElement = selection.getSelectedElement();
if ( selectedElement && selectedElement.is( 'element', 'media' ) ) {
return selectedElement;
}
return null;
}
/**
* Creates a media element and inserts it into the model.
*
* **Note**: This method will use {@link module:engine/model/model~Model#insertContent `model.insertContent()`} logic of inserting content
* if no `insertPosition` is passed.
*
* @param url An URL of an embeddable media.
* @param findOptimalPosition If true it will try to find optimal position to insert media without breaking content
* in which a selection is.
*/
export function insertMedia( model: Model, url: string, selectable: Selectable, findOptimalPosition: boolean ): void {
model.change( writer => {
const mediaElement = writer.createElement( 'media', { url } );
model.insertObject( mediaElement, selectable, null, {
setSelection: 'on',
findOptimalPosition: findOptimalPosition ? 'auto' : undefined
} );
} );
}
/**
* Type for commonly grouped function parameters across this package.
*/
export type MediaOptions = {
elementName: string;
renderMediaPreview?: boolean;
renderForEditingView?: boolean;
};