Modify links when inserted by WYSIWYG editor

The HTML for the inserted internal links are generated by Javascript, so I’m not aware of any easy way to change it.

The HTML generation is controlled from the wpLink.htmlUpdate method (HTML mode) and the
wpLink.mceUpdate method (TinyMCE mode), in the /wp-includes/js/wplink.js file.

Here are some ideas:

Add a query parameter to the inserted links:

We could add a query parameter, containing the post ID info, to the url of the inserted links, for example:

http://example.dev/hello-world/?wpse_pid=475

with the following:

/**
 * Append the wpse_pid query argument to inserted links
 *
 * @see http://wordpress.stackexchange.com/a/170836/26350
 */

add_filter( 'wp_link_query_args', function( $query ) {
    add_filter( 'post_link', 'wpse_post_link', 10, 2 );
    return $query;
});

add_filter( 'wp_link_query', function( $query ) {
    remove_filter( 'post_link', 'wpse_post_link', 10 );
    return $query;   
});

function wpse_post_link( $permalink, $post )
{
    if( false === stripos( $permalink, '?p=' ) )
            $permalink = add_query_arg( array( 'wpse_pid' => $post->ID ), $permalink );
    return $permalink;
}

Here’s a screenshot showing this in action:

link with the wpse_pid parameter

Override the wpLink.mceUpdate method:

The following hack is just for fun, since the method might change in the future.

This is addition to the above code snippets.

/** 
 * Override the wpLink.mceUpdate method to modify the inserted link HTML.
 *
 * @see http://wordpress.stackexchange.com/a/170836/26350
 */

add_action( 'admin_footer-post.php', function(){
?>
<script>
jQuery( document ).ready( function( $ ){
    wpLink.mceUpdate = function(){
            var link,
            attrs = wpLink.getAttrs(),
            editor = tinyMCE.activeEditor;

            wpLink.close();
            editor.focus();

            if ( tinymce.isIE ) {
                editor.selection.moveToBookmark( editor.windowManager.bookmark );
            }
            link = editor.dom.getParent( editor.selection.getNode(), 'a[href]' );

            // If the values are empty, unlink and return
            if ( ! attrs.href || attrs.href == 'http://' ) {        
                editor.execCommand( 'unlink' );
                return;
            }

            // Set the class attribute.
            attrs.class="wpse_pid";

            // Grab the value of the wpse_pid parameter and use as id attribute.
            // Modified version of http://www.sitepoint.com/url-parameters-jquery/
            var results = new RegExp('[\?&]wpse_pid=([^&#]*)').exec( attrs.href );
            attrs.id = ( results != null ) ? 'wpse_pid_' + results[1] : ''

            // Remove the ?wpse_pid=* part
            // Modified version of http://stackoverflow.com/a/7126657/2078474
            attrs.href = attrs.href.replace(/[\?&]?wpse_pid=([^&]$|[^&]*)/i, "");

            if ( link ) {
                editor.dom.setAttribs( link, attrs );
            } else {
                editor.execCommand( 'mceInsertLink', false, attrs );
            }

            // Move the cursor to the end of the selection
            editor.selection.collapse();
    }
});
</script>
<?php
}, 99 );

The HTML of the inserted link has now the form:

<a id="wpse_pid_475" 
   class="wpse_pid"  
   title="Hello World" 
   href="http://example.dev/hello-world/">Hello World</a>

where the unmodified link is:

<a title="Hello World" 
   href="http://example.dev/hello-world/">Hello World</a>

Here I used the class and id attributes, since they seems to be supported attributes by the tinyMCE editor. I tried attrs.data but that didn’t work. You might want to look deeper into that.

It should be similar to override the wpLink.htmlUpdate method. But this is just proof of concept 😉

Another idea would be to scan the links of the post content during updates and modify them with some clever regexp replaces or some PHP DOM modifications.

Hopefully you can take this further and modify to your needs.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)