Index: src/wp-admin/admin-ajax.php =================================================================== --- src/wp-admin/admin-ajax.php (revision 28353) +++ src/wp-admin/admin-ajax.php (working copy) @@ -58,7 +58,7 @@ 'wp-remove-post-lock', 'dismiss-wp-pointer', 'upload-attachment', 'get-attachment', 'query-attachments', 'save-attachment', 'save-attachment-compat', 'send-link-to-editor', 'send-attachment-to-editor', 'save-attachment-order', 'heartbeat', 'get-revision-diffs', - 'save-user-color-scheme', 'update-widget', 'query-themes', + 'save-user-color-scheme', 'update-widget', 'query-themes', 'filter-content' ); // Register core Ajax calls. Index: src/wp-admin/includes/ajax-actions.php =================================================================== --- src/wp-admin/includes/ajax-actions.php (revision 28353) +++ src/wp-admin/includes/ajax-actions.php (working copy) @@ -2220,3 +2220,24 @@ wp_send_json_success( $api ); } + +/** + * Apply `the_content` filters to a string based on the post ID. + * + * @since 4.0.0 + */ +function wp_ajax_filter_content() { + global $post; + + if ( ! $post = get_post( (int) $_REQUEST['post_ID'] ) ) { + wp_send_json_error(); + } + + if ( ! current_user_can( 'read_post', $post->ID ) ) { + wp_send_json_error(); + } + + setup_postdata( $post ); + + wp_send_json_success( apply_filters( 'the_content', wp_unslash( $_POST['content'] ) ) ); +} Index: src/wp-includes/js/mce-view.js =================================================================== --- src/wp-includes/js/mce-view.js (revision 28353) +++ src/wp-includes/js/mce-view.js (working copy) @@ -354,27 +354,7 @@ */ wp.mce.media = { loaded: false, - /** - * @global wp.shortcode - * - * @param {string} content - * @returns {Object} - */ - toView: function( content ) { - var match = wp.shortcode.next( this.shortcode, content ); - - if ( ! match ) { - return; - } - - return { - index: match.index, - content: match.content, - options: { - shortcode: match.shortcode - } - }; - }, + toView: wp.mce.gallery.toView, /** * Called when a TinyMCE view is clicked for editing. @@ -690,4 +670,76 @@ View: wp.mce.media.PlaylistView } ); wp.mce.views.register( 'playlist', wp.mce.playlist ); + + wp.mce.embed = { + shortcode: 'embed', + toView: wp.mce.gallery.toView, + View: wp.mce.View.extend( { + className: 'editor-embed', + initialize: function( options ) { + this.players = []; + this.content = options.content; + this.parsed = false; + this.shortcode = options.shortcode; + _.bindAll( this, 'setHtml', 'setNode', 'fetch' ); + $( this ).on( 'ready', this.setNode ); + }, + unbind: function() { + var self = this; + this.pauseAllPlayers(); + _.each( this.players, function ( player ) { + self.removePlayer( player ); + } ); + this.players = []; + }, + setNode: function ( e, node ) { + this.node = node; + if ( this.parsed ) { + this.parseMediaShortcodes(); + } else { + this.fetch(); + } + }, + fetch: function () { + wp.ajax.send( 'filter-content', { + data: { + post_ID: $( '#post_ID' ).val(), + content: this.shortcode.string() + } + } ).done( this.setHtml ); + }, + setHtml: function ( content ) { + var toolbar = '
', + scripts = $( content ).find( 'script' ); + $( this.node ).html( toolbar + content ); + if ( scripts ) { + scripts.each( function() { + var element = document.createElement( 'script' ); + element.type = 'text/javascript'; + element.src = $( this ).attr( 'src' ); + tinymce.activeEditor.contentDocument.getElementsByTagName( 'head' )[0].appendChild( element ); + } ); + } + this.parseMediaShortcodes(); + }, + parseMediaShortcodes: function () { + var self = this; + $( '.wp-audio-shortcode, .wp-video-shortcode', this.node ).each( function ( i, element ) { + self.players.push( element, self.mejsSettings ); + } ); + }, + getHtml: function() { + if ( ! this.parsed ) { + return ''; + } + return this.parsed; + } + } ), + edit: function() {} + }; + + _.extend( wp.mce.embed.View.prototype, wp.media.mixin ); + + wp.mce.views.register( 'embed', wp.mce.embed ); + }(jQuery)); Index: src/wp-includes/js/tinymce/plugins/wpview/plugin.js =================================================================== --- src/wp-includes/js/tinymce/plugins/wpview/plugin.js (revision 28353) +++ src/wp-includes/js/tinymce/plugins/wpview/plugin.js (working copy) @@ -168,6 +168,12 @@ event.content = wp.mce.views.toViews( event.content ); }); + editor.on( 'PastePreProcess', function( event ) { + if ( event.content.match( /^\s*(https?:\/\/[^\s"]+)\s*$/im ) ) { + event.content = '[embed]' + event.content + '[/embed]'; + } + } ); + // When the editor's content has been updated and the DOM has been // processed, render the views in the document. editor.on( 'SetContent', function( event ) {