1

I'm developing a client website with Wordpress (3.3) but have found that the image caption feature strips out any HTML tags.

The resulting caption is plain text which makes proper image crediting difficult. Also being a client website, WYSIWYG editing is required.

For example if my shortcode is:

[caption caption="This is my <em>example</em> caption"]
<a href="http://example.com/image.jpg">
<img src="http://example.com/image-300x224.jpg" alt=""/>
</a>
[/caption]

The tags are stripped from the caption attribute like so:

[caption caption="This is my example caption"]
<a href="http://example.com/image.jpg">
<img src="http://example.com/image-300x224.jpg" alt=""/>
</a>
[/caption]

The tags I'd most like to preserve are <em>, <sup>, <sub>, <span> and <a>.

I haven't found any existing plugins to fix this except for links.

Any ideas on how to go about this and which functions to override?

6
  • It probably won't help now, it does look like this will be fixed for 3.4: Support HTML in image captions - core.trac.wordpress.org/ticket/18311 Jan 17, 2012 at 5:34
  • use html5 figcaption ;) Jan 17, 2012 at 13:27
  • As you are new here, mnorrish, be advised that you should upvote answers you like and accept the most useful one (by clicking the grey tick next to it).
    – Raphael
    Jan 17, 2012 at 13:36
  • I like the figure/figcaption tags but found that switching between the Visual and HTML editors strips the <figure> tags.
    – mnorrish
    Jan 18, 2012 at 1:56
  • Yea, WP does not really support HTML5 yet. :-/
    – Raphael
    Jan 18, 2012 at 10:00

3 Answers 3

3

I'm glad that better support should be added in version 3.4 but for now I've fixed the issue by changing the behaviour of image insertion so that it doesn't use the [caption] shortcode.

Here's what I added to functions.php:

add_filter( 'disable_captions', create_function('$a', 'return true;') );

function image_send_to_editor_2($html, $id, $caption, $title, $align, $url, $size, $alt) {
    if ( !$caption ) {
        return $html;
    } else {
        $width = 'auto';
        if ( preg_match( '/width="([0-9]+)/', $html, $matches ) ) {
            $width = $matches[1] . 'px';
        }

        $output = '<div id="attachment-' . $id . '" class="wp-caption align' . $align . '" style="width: ' . $width . ';">';
        $output .= $html;
        $output .= '<p class="wp-caption-text">' . $caption . '</p>';
        $output .= '</div>';

        return $output;
    }

}

add_filter('image_send_to_editor', 'image_send_to_editor_2', 10, 8);

This works best with the TinyMCE Advanced plugin with its option to stop removing (and adding) <p> and <br /> tags enabled.

2
  • Using <dl> for this purpose strikes me as odd, especially from a semantic viewpoint. Also, it is not stable against changes to Wordpress and your preferences; if anything changes, you have to manually edit all prior posts or bear with broken/different looking posts.
    – Raphael
    Jan 18, 2012 at 9:36
  • 1
    Oops that's right. It's only in the editor that a <dl> is used. I'll change this to a <div> for the container and <p> for the caption.
    – mnorrish
    Jan 18, 2012 at 20:22
0

Okay, your problem seems interesting.

One thing I could think of is:

[caption caption="caption1"]
<a href="http://example.com/image.jpg">
<img src="http://example.com/image-300x224.jpg" alt=""/>
</a>
[/caption]

Store a custom meta field for the post with name 'caption1' and your HTML caption. Use a filter on the_content() to convert all caption1 into your HTML caption by pulling it from postmeta.

3
  • This is a crowbar solution, but should be fine in most cases. Note that if you want to be able to use shortcodes in your caption, you will have do run do_shortcodes on the replacement string. Also, if you have other plugins that work on filter the_content you might get unexpected results depending on the order in which the registered functions are executed.
    – Raphael
    Jan 18, 2012 at 9:40
  • I do not understand when you say I have to run do_shortcodes on the replacement string. If you are worried about the order of filters running on the_content you can choose a much specific caption name like mycap_capname to ensure that no other filters pick it up. Unexpected results can be easily avoided.
    – Sterex
    Jan 18, 2012 at 12:27
  • Hm, my bad. Codex says that do_shortcodes is registred on the_content, too, with priority 11. So as long as you add your filter with priority at most 10, you are fine.
    – Raphael
    Jan 18, 2012 at 14:09
0

First of all, you can put stuff into captions like that:

[caption ...]
  <a ...> ... </a>
  Your caption text
[/caption]

This works with most formatting HTML. It fails (iirc) for links, and it also might not place the caption exactly the way you like it.

I have observed that stuff produced by shortcodes in captions is not sanitised, though. Therefore, my workaround uses the excellent and ever useful plugin Shortcode Exec PHP and create a shortcode captiontext with this PHP:

return '<div style="text-align: center; margin: 5px 0px -20px 0px;">'.do_shortcode($content).'</div>';

Adjust styling information to your liking, obviously. Now you can use it like this

[caption ...]
  <a ...> ... </a>
  [captiontext]Your caption text[/captiontext]
[/caption]

and you can use all the HTML you want.

Edit: Advantages of this solution: It is (relatively) stable against future changes in Wordpress and your taste. As long as shortcodes are handled the way they are now, you can adjust your shortcode definition to compensate whatever changes in all posts ever written without having to touch every single one of them. Furthermore, the workaround is nicely integrated into Wordpress' natural flow; in particular, you can use other shortcodes in your caption. Last but not least, you do not have to touch any theme or core file for the workaround but use a mature plugin instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.