1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | import { Plugin } from 'ckeditor5/src/core';
|
11 | import { LiveRange, LivePosition } from 'ckeditor5/src/engine';
|
12 | import { Clipboard } from 'ckeditor5/src/clipboard';
|
13 | import { Delete } from 'ckeditor5/src/typing';
|
14 | import { Undo } from 'ckeditor5/src/undo';
|
15 | import { global } from 'ckeditor5/src/utils';
|
16 |
|
17 | import MediaEmbedEditing from './mediaembedediting';
|
18 | import { insertMedia } from './utils';
|
19 |
|
20 | const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w-]+\.[\w-.~:/?#[\]@!$&'()*+,;=%]+$/;
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | export default class AutoMediaEmbed extends Plugin {
|
29 | |
30 |
|
31 |
|
32 | static get requires() {
|
33 | return [ Clipboard, Delete, Undo ];
|
34 | }
|
35 |
|
36 | |
37 |
|
38 |
|
39 | static get pluginName() {
|
40 | return 'AutoMediaEmbed';
|
41 | }
|
42 |
|
43 | |
44 |
|
45 |
|
46 | constructor( editor ) {
|
47 | super( editor );
|
48 |
|
49 | |
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | this._timeoutId = null;
|
57 |
|
58 | |
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | this._positionToInsert = null;
|
66 | }
|
67 |
|
68 | |
69 |
|
70 |
|
71 | init() {
|
72 | const editor = this.editor;
|
73 | const modelDocument = editor.model.document;
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | this.listenTo( editor.plugins.get( 'ClipboardPipeline' ), 'inputTransformation', () => {
|
79 | const firstRange = modelDocument.selection.getFirstRange();
|
80 |
|
81 | const leftLivePosition = LivePosition.fromPosition( firstRange.start );
|
82 | leftLivePosition.stickiness = 'toPrevious';
|
83 |
|
84 | const rightLivePosition = LivePosition.fromPosition( firstRange.end );
|
85 | rightLivePosition.stickiness = 'toNext';
|
86 |
|
87 | modelDocument.once( 'change:data', () => {
|
88 | this._embedMediaBetweenPositions( leftLivePosition, rightLivePosition );
|
89 |
|
90 | leftLivePosition.detach();
|
91 | rightLivePosition.detach();
|
92 | }, { priority: 'high' } );
|
93 | } );
|
94 |
|
95 | editor.commands.get( 'undo' ).on( 'execute', () => {
|
96 | if ( this._timeoutId ) {
|
97 | global.window.clearTimeout( this._timeoutId );
|
98 | this._positionToInsert.detach();
|
99 |
|
100 | this._timeoutId = null;
|
101 | this._positionToInsert = null;
|
102 | }
|
103 | }, { priority: 'high' } );
|
104 | }
|
105 |
|
106 | |
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 | _embedMediaBetweenPositions( leftPosition, rightPosition ) {
|
115 | const editor = this.editor;
|
116 | const mediaRegistry = editor.plugins.get( MediaEmbedEditing ).registry;
|
117 |
|
118 | const urlRange = new LiveRange( leftPosition, rightPosition );
|
119 | const walker = urlRange.getWalker( { ignoreElementEnd: true } );
|
120 |
|
121 | let url = '';
|
122 |
|
123 | for ( const node of walker ) {
|
124 | if ( node.item.is( '$textProxy' ) ) {
|
125 | url += node.item.data;
|
126 | }
|
127 | }
|
128 |
|
129 | url = url.trim();
|
130 |
|
131 |
|
132 | if ( !url.match( URL_REGEXP ) ) {
|
133 | urlRange.detach();
|
134 |
|
135 | return;
|
136 | }
|
137 |
|
138 |
|
139 | if ( !mediaRegistry.hasMedia( url ) ) {
|
140 | urlRange.detach();
|
141 |
|
142 | return;
|
143 | }
|
144 |
|
145 | const mediaEmbedCommand = editor.commands.get( 'mediaEmbed' );
|
146 |
|
147 |
|
148 | if ( !mediaEmbedCommand.isEnabled ) {
|
149 | urlRange.detach();
|
150 |
|
151 | return;
|
152 | }
|
153 |
|
154 |
|
155 | this._positionToInsert = LivePosition.fromPosition( leftPosition );
|
156 |
|
157 |
|
158 | this._timeoutId = global.window.setTimeout( () => {
|
159 | editor.model.change( writer => {
|
160 | this._timeoutId = null;
|
161 |
|
162 | writer.remove( urlRange );
|
163 | urlRange.detach();
|
164 |
|
165 | let insertionPosition;
|
166 |
|
167 |
|
168 |
|
169 | if ( this._positionToInsert.root.rootName !== '$graveyard' ) {
|
170 | insertionPosition = this._positionToInsert;
|
171 | }
|
172 |
|
173 | insertMedia( editor.model, url, insertionPosition, false );
|
174 |
|
175 | this._positionToInsert.detach();
|
176 | this._positionToInsert = null;
|
177 | } );
|
178 |
|
179 | editor.plugins.get( 'Delete' ).requestUndoOnBackspace();
|
180 | }, 100 );
|
181 | }
|
182 | }
|