The WordPress media manager allows you to add captions to your images, which can be inserted into your post content wrapped in the caption shortcode.
You can see that I’ve placed anchor tags in the photo caption to link to the photo credit:
Photo credit: <a href="http://www.flickr.com/photos/nattu/2735064420">nattu</a></code>
When you click the “Insert into Post” button, you end up with this markup in your editor:
[ caption id="attachment_1133" align="alignleft" width="300" caption="Photo credit: <a href="http://www.flickr.com/photos/nattu/2735064420">nattu</a>"] <a data-rel="prettyPhoto" title="The Entrance" href="http://localhost/agility/wp-content/uploads/2012/03/TheEntrance.jpg"> <img src="http://localhost/agility/wp-content/uploads/2012/03/TheEntrance-300x199.jpg" alt="" title="The Entrance" width="300" height="199" class="scale-with-grid size-medium wp-image-1133" /></a>[/caption]
The Problem
The issue is that all the HTML entities in the caption attribute (specifically, the anchor tags) are encoded. That is, instead of
Photo credit: <a href="http://www.flickr.com/photos/nattu/2735064420">nattu</a>
we have
Photo credit: <a href="http://www.flickr.com/photos/nattu/2735064420">nattu</a>
As a result, instead of getting the desired output in our caption:
Photo credit: <a href="http://www.flickr.com/photos/nattu/2735064420">nattu</a>
We get the encoded HTML markup instead:
Photo credit: <a href="http://www.flickr.com/photos/nattu/2735064420">nattu</a>
The Solution
Now, the HTML entities have to be escaped in order to safely place them in the caption=”” attribute of the caption shortcode (or at least the double quotes do), and in any event it’s very inconvenient to decode the entities manually. What we’ll need to do is decode them programmatically when the shortcode is processed at run time.
Helpfully, WordPress’s img_caption_shortcode function (wp-includes/media.php) includes a filter that allows us to hook in and override the caption. Here’s the original function:
/** * The Caption shortcode. * * Allows a plugin to replace the content that would otherwise be returned. The * filter is 'img_caption_shortcode' and passes an empty string, the attr * parameter and the content parameter values. * * The supported attributes for the shortcode are 'id', 'align', 'width', and * 'caption'. * * @since 2.6.0 * * @param array $attr Attributes attributed to the shortcode. * @param string $content Optional. Shortcode content. * @return string */ function img_caption_shortcode($attr, $content = null) { // Allow plugins/themes to override the default caption template. $output = apply_filters('img_caption_shortcode', '', $attr, $content); if ( $output != '' ) return $output; extract(shortcode_atts(array( 'id' => '', 'align' => 'alignnone', 'width' => '', 'caption' => '' ), $attr)); if ( 1 > (int) $width || empty($caption) ) return $content; if ( $id ) $id = 'id="' . esc_attr($id) . '" '; return '<div ' . $id . 'class="wp-caption ' . esc_attr($align) . '" style="width: ' . (10 + (int) $width) . 'px">' . do_shortcode( $content ) . '<p class="wp-caption-text">' . $caption . '</p></div>'; } add_shortcode('gallery', 'gallery_shortcode');
We’re just going to hook in and use the same code, but add a line of our own to decode the HTML tags.
$caption = html_entity_decode( $caption );
The Code
So, our final function, which I’ve placed in functions.php, looks like this:
//Our custom caption shortcode function is based on the WordPress Core version with a small change function custom_img_caption_shortcode( $a , $attr, $content = null) { extract(shortcode_atts(array( 'id' => '', 'align' => 'alignnone', 'width' => '', 'caption' => '' ), $attr)); if ( 1 > (int) $width || empty($caption) ) return $content; $caption = html_entity_decode( $caption ); //Here's our new line to decode the html tags if ( $id ) $id = 'id="' . esc_attr($id) . '" '; return '<div ' . $id . 'class="wp-caption ' . esc_attr($align) . '" style="width: ' . (10 + (int) $width) . 'px">' . do_shortcode( $content ) . '<p class="wp-caption-text">' . $caption . '</p></div>'; } //Add the filter to override the standard shortcode add_filter( 'img_caption_shortcode', 'custom_img_caption_shortcode', 10, 3 );
And that’s it! Just pop that code into your functions.php and you should be able to add links to your photo captions. If anyone knows a better way of doing this, let me know in the comments. Enjoy!