Skip to content

Commit 171ef31

Browse files
committed
Merge branch 't/13214b' into major
2 parents dea7ff8 + cc0a9ae commit 171ef31

File tree

8 files changed

+746
-0
lines changed

8 files changed

+746
-0
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ New Features:
99
* [#13215](http://dev.ckeditor.com/ticket/13215): Added ability to cancel fetching a resource by the Embed plugins.
1010
* [#13213](http://dev.ckeditor.com/ticket/13213): Added [`dialog#setState()`](http://docs.ckeditor.com/#!/api/CKEDITOR.dialog-method-setState) method and used in in Embed dialog to indicate that a resource is being loaded.
1111
* [#13337](http://dev.ckeditor.com/ticket/13337): Added the [`repository.onWidget()`](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget.repository-method-onWidget) method – a convenient way to listen to [widget](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget) events through the [repository](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget.repository).
12+
* [#13214](http://dev.ckeditor.com/ticket/13214): Added support for pasting links that convert into embeddable resources on the fly.
1213

1314
Fixed Issues:
1415

plugins/autoembed/plugin.js

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/**
2+
* @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md or http://ckeditor.com/license
4+
*/
5+
6+
'use strict';
7+
8+
( function() {
9+
CKEDITOR.plugins.add( 'autoembed', {
10+
requires: 'autolink,undo',
11+
12+
init: function( editor ) {
13+
var currentId = 1;
14+
15+
editor.on( 'paste', function( evt ) {
16+
if ( evt.data.dataTransfer.getTransferType( editor ) == CKEDITOR.DATA_TRANSFER_INTERNAL ) {
17+
return;
18+
}
19+
20+
var data = evt.data.dataValue,
21+
parsedData,
22+
link;
23+
24+
// Expecting exactly one <a> tag spanning the whole pasted content.
25+
if ( data.match( /^<a [^<]+<\/a>$/i ) ) {
26+
parsedData = CKEDITOR.htmlParser.fragment.fromHtml( data );
27+
28+
// Embed only links with a single text node with a href attr which equals its text.
29+
if ( parsedData.children.length != 1 )
30+
return;
31+
32+
link = parsedData.children[ 0 ];
33+
34+
if ( link.type == CKEDITOR.NODE_ELEMENT && link.getHtml() == link.attributes.href ) {
35+
evt.data.dataValue = '<a data-cke-autoembed="' + ( ++currentId ) + '"' + data.substr( 2 );
36+
}
37+
}
38+
39+
}, null, null, 20 ); // Execute after autolink.
40+
41+
editor.on( 'afterPaste', function() {
42+
autoEmbedLink( editor, currentId );
43+
} );
44+
}
45+
} );
46+
47+
function autoEmbedLink( editor, id ) {
48+
var anchor = editor.editable().findOne( 'a[data-cke-autoembed="' + id + '"]' );
49+
50+
if ( !anchor || !anchor.data( 'cke-saved-href' ) ) {
51+
return;
52+
}
53+
54+
var href = anchor.data( 'cke-saved-href' ),
55+
widgetDef = CKEDITOR.plugins.autoEmbed.getWidgetDefinition( editor, href );
56+
57+
if ( !widgetDef ) {
58+
window.console && window.console.log(
59+
'[CKEDITOR.plugins.autoEmbed] Incorrect config.autoEmbed_widget value. ' +
60+
'No widget definition found.'
61+
);
62+
return;
63+
}
64+
65+
// TODO Move this to a method in the widget plugin. #13408
66+
var defaults = typeof widgetDef.defaults == 'function' ? widgetDef.defaults() : widgetDef.defaults,
67+
element = CKEDITOR.dom.element.createFromHtml( widgetDef.template.output( defaults ) ),
68+
instance,
69+
wrapper = editor.widgets.wrapElement( element, widgetDef.name ),
70+
temp = new CKEDITOR.dom.documentFragment( wrapper.getDocument() );
71+
72+
temp.append( wrapper );
73+
instance = editor.widgets.initOn( element, widgetDef );
74+
75+
if ( !instance ) {
76+
finalizeCreation();
77+
return;
78+
}
79+
80+
instance.loadContent( href, {
81+
callback: function() {
82+
// DOM might be invalidated in the meantime, so find the anchor again.
83+
var anchor = editor.editable().findOne( 'a[data-cke-autoembed="' + id + '"]' ),
84+
range = editor.createRange();
85+
86+
// Anchor might be removed in the meantime.
87+
if ( anchor ) {
88+
range.setStartAt( anchor, CKEDITOR.POSITION_BEFORE_START );
89+
range.setEndAt( anchor, CKEDITOR.POSITION_AFTER_END );
90+
91+
editor.editable().insertElementIntoRange( wrapper, range );
92+
}
93+
94+
finalizeCreation();
95+
},
96+
97+
error: finalizeCreation
98+
} );
99+
100+
function finalizeCreation() {
101+
editor.widgets.finalizeCreation( temp );
102+
}
103+
}
104+
105+
CKEDITOR.plugins.autoEmbed = {
106+
/**
107+
* Gets definition of a widget that should be used to automatically embed the specified link.
108+
*
109+
* This method uses value of the {@link CKEDITOR.config#autoEmbed_widget} option.
110+
*
111+
* @since 4.5.0
112+
* @param {CKEDITOR.editor} editor
113+
* @param {String} url URL to be embedded.
114+
* @returns {CKEDITOR.plugins.widget.definition/null} Definition of the widget to be used to embed the link.
115+
*/
116+
getWidgetDefinition: function( editor, url ) {
117+
var opt = editor.config.autoEmbed_widget || 'embed,embedSemantic',
118+
name,
119+
widgets = editor.widgets.registered;
120+
121+
if ( typeof opt == 'string' ) {
122+
opt = opt.split( ',' );
123+
124+
while ( ( name = opt.shift() ) ) {
125+
if ( widgets[ name ] ) {
126+
return widgets[ name ];
127+
}
128+
}
129+
} else if ( typeof opt == 'function' ) {
130+
return widgets[ opt( url ) ];
131+
}
132+
133+
return null;
134+
}
135+
};
136+
137+
/**
138+
* Specifies which widget to use to automatically embed a link. The default value
139+
* of this option defines that either the [Embed](ckeditor.com/addon/embed) or
140+
* [Semantic Embed](ckeditor.com/addon/embedsemantic) widgets will be used, depending on which is enabled.
141+
*
142+
* The general behavior:
143+
*
144+
* * If string (widget names separated by commas) is provided, then first of the listed widgets which is registered
145+
* will be used. For example, if `'foo,bar,bom'` is set and widgets `'bar'` and `'bom'` are registered, then `'bar'`
146+
* will be used.
147+
* * If a callback is specified, then it will be executed with the URL to be embedded and it should return a
148+
* name of the widget to be used. It allows to use different embed widgets for different URLs.
149+
*
150+
* Example:
151+
*
152+
* // Defines that embedSemantic should be used (regardless of whether embed is defined).
153+
* config.autoEmbed_widget = 'embedSemantic';
154+
*
155+
* Using with custom embed widgets:
156+
*
157+
* config.autoEmbed_widget = 'customEmbed';
158+
*
159+
* **Note:** Plugin names are always lower case, while widget names are not, so widget names do not have to equal plugin names.
160+
* For example, there is the `embedsemantic` plugin and `embedSemantic` widget.
161+
*
162+
* @since 4.5.0
163+
* @cfg {String/Function} [autoEmbed_widget='embed,embedSemantic']
164+
* @member CKEDITOR.config
165+
*/
166+
} )();

plugins/autolink/plugin.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md or http://ckeditor.com/license
4+
*/
5+
6+
'use strict';
7+
8+
CKEDITOR.plugins.add( 'autolink', {
9+
requires: 'clipboard',
10+
11+
init: function( editor ) {
12+
editor.on( 'paste', function( evt ) {
13+
var data = evt.data.dataValue;
14+
15+
if ( evt.data.dataTransfer.getTransferType( editor ) == CKEDITOR.DATA_TRANSFER_INTERNAL ) {
16+
return;
17+
}
18+
19+
// If we found "<" it means that most likely there's some tag and we don't want to touch it.
20+
if ( data.indexOf( '<' ) > -1 ) {
21+
return;
22+
}
23+
24+
// Regex by Imme Emosol.
25+
data = data.replace( /^(https?|ftp):\/\/(-\.)?([^\s\/?\.#-]+\.?)+(\/[^\s]*)?[^\s\.,]$/ig , '<a href="$&">$&</a>' );
26+
27+
// If link was discovered, change the type to 'html'. This is important e.g. when pasting plain text in Chrome
28+
// where real type is correctly recognized.
29+
if ( data != evt.data.dataValue ) {
30+
evt.data.type = 'html';
31+
}
32+
33+
evt.data.dataValue = data;
34+
} );
35+
}
36+
} );

0 commit comments

Comments
 (0)