do_shortcode() in twentyeleven theme

It looks like twenty ten displays the excerpt on category archives.

If you’re using manual excerpts, this is an easy fix. Just add this line of code to your theme’s functions.php file. It tells wordpress to run the excerpt through the do_shortcode function/filter.

add_filter( 'the_excerpt', 'do_shortcode' );

If you’re not using manual excerpts, we have to go a little deeper. The function the_excerpt only returns the post excerpt empty or not. It doesn’t grab parts of the content and throw them in if the excerpt is empty. Which means that WordPress is hooking into either the_excerpt or get_the_excerpt filter somewhere along the way. in wp-includes/default-filters.php we find the culprit:

add_filter( 'get_the_excerpt', 'wp_trim_excerpt'  );

The function grabs parts of the post content, removing shortcodes along the way, and returns it as the excerpt:

<?php
function wp_trim_excerpt($text) {
       $raw_excerpt = $text;
       if ( '' == $text ) {
          $text = get_the_content('');

          $text = strip_shortcodes( $text );

          $text = apply_filters('the_content', $text);
         $text = str_replace(']]>', ']]&gt;', $text);
          $text = strip_tags($text);
          $excerpt_length = apply_filters('excerpt_length', 55);
          $excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
          $words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
          if ( count($words) > $excerpt_length ) {
              array_pop($words);
              $text = implode(' ', $words);
              $text = $text . $excerpt_more;
          } else {
              $text = implode(' ', $words);
          }
      }
      return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}

So we need to remove this default filter and repalce it with our own.

<?php
remove_filter( 'get_the_excerpt', 'wp_trim_excerpt', 10 );
add_filter( 'get_the_excerpt', 'wpse27049_wp_trim_excerpt', 99, 1 );
function wpse27049_wp_trim_excerpt( $text )
{
    if ( '' == $text ) {
        $text = get_the_content('');
        $text = substr( $text, 0, 55 );
        $excerpt_more = apply_filters( 'excerpt_more', '[...]' );
        $text = $text . $excerpt_more;
    }
    return $text;

}

Alternatively, you could just return the entire content if there’s no excerpt:

<?php
remove_filter( 'get_the_excerpt', 'wp_trim_excerpt', 10 );
add_filter( 'get_the_excerpt', 'wpse27049_wp_trim_excerpt', 99, 1 );
function wpse27049_wp_trim_excerpt( $text )
{
    if ( '' == $text ) {
        $text = get_the_content('');
    }
    return $text;

}

As a plugin: http://pastie.org/2439045