1

I have a theme for my mobile site that requires the <!--more--> tag in my posts for it to display an excerpt of my post's content.

I've got over 2000 posts already, and its going to take forever to add the tag in all my posts. I don't want to use a plugin, cause I've used one that wasn't stable at all.

I just need a snippet I can hook up in my theme's files that will add the more tag after a specific character or word count in all my posts, and in every post I publish after that.

2
  • As the scenario you are in here is not clear, I would suggest you to have a look into the Codex for more details Mar 10, 2014 at 10:01
  • Thanks for the feedback maruti, I clearly understood wordpress's explanation of the more tag but I was finding it difficult setting a particular string count before the tag comes in, I want to be able to specify the amount of characters rather than use wordpress's default string count. I hope you understand, thanks! Mar 11, 2014 at 23:26

2 Answers 2

1

If you want to control the string count, then you can do it by the following.

Put the below code in the active theme's functions.php file:--

function custom_excerpt_length( $length ) {
    return 20; // You can change the number here as per your need.
}
add_filter( 'excerpt_length', 'custom_excerpt_length', 999 );

By default, excerpt length is set to 55 words. To change excerpt length to 20 words using excerpt_length filter, add the above code to functions.php file in your theme:

For more details check the Codex

0

The Read More (<!--more-->) tag is processed by get_the_content() in wp-includes/post-template.php. It does not run any hookable filters on its content input; however, that comes from the $pages global which can be modified at the time it is set up by hooking the the_post action.

The following function will auto-insert a <!--more--> tag at the first space after 280 characters (skipping HTML tags, and counting sequences of whitespace as a single character), if there isn’t one already present:

\add_action(
  'the_post',
  function($post, $query) {
    global $pages, $shortcode_tags;
    // Matches an HTML entity, block of whitespace, or single character:
    static $rxChar = '&#?+\\w++;|\\s++|[^<]';
    // Matches an HTML tag:
    static $rxTag = '<[^>]*+>';
    // Based on regex in from `get_shortcode_regex`
    $tagnames = \array_keys($shortcode_tags);
    $tagregexp = \join('|', \array_map('preg_quote', $tagnames));
    $rxShortcode =
      '\\['                 // Opening bracket
      . '\\[?+'             // 1: Optional second opening bracket for escaping
      . '(?&shortcode_tag)' // 2: Shortcode name
      . '(?![\\w-])'        // Not followed by word character or hyphen
      . '[^\\]\\/]*+'       // Not a closing bracket or forward slash
      . '(?:'
      .   '\\/(?!\\])'      // A forward slash not followed by a closing bracket
      .   '[^\\]\\/]*+'     // Not a closing bracket or forward slash
      . ')*+'
      . '\\/?+'             // 4: Self closing tag ...
      . '\\]'               // ... and closing bracket
      . '\\]?+';            // 6: Optional second closing brocket for escaping
    // Matches zero or more HTML tags or shortcode tags
    $rxTags = "(?:$rxTag|$rxShortcode)*+";
    $regex = "/(?(DEFINE)(?<shortcode_tag>$tagregexp)(?<char>$rxChar)"
      . "(?<tags>$rxTags))"
      // At least 280 characters, from the start, followed by a space
      // (catastrophic failure with general repetition quantifier mitigated
      // against by splitting into two multiplicative repetitions):
      . '^(?:(?:(?&tags)(?&char)){10}+){28}+(?&tags)(?:(?&char)(?&tags))*?'
      . '(?=\\s)/u';
    foreach ($pages as $i => $page) {
      if (\strpos($page, '<!--more') === false) {
        $page = \preg_replace($regex, '$0<!--more-->', $page, 1);
        if ($page !== null) {
          $pages[$i] = $page;
        } else {
          trigger_error(
            "Regex failure inserting 'Read More' tag into `$pages[$i]`."
          );
        }
      }
    }
  },
  10, 2
);

It should be fairly self-explanatory, though I’ll add a few notes on the regex:

  • The u (UTF-8) modifier ensures that multibyte characters count only as one.
  • The + (possessive) quantifier massively optimizes the performance and memory footprint (where the token can’t consume any of the following token). However, it doesn’t seem to make much difference mitigating against failure when applied to the general repetition quantifier, so this has been split into repetitions of repetitions. And nonetheless, in the event of failure the content will be left unchanged.
  • The ? (lazy) quantifier ensures the first space after 280 characters is stopped at, not the last.

(I know this question was asked more than 4 years ago, but it hadn’t been answered; I found it looking for a solution for exactly the same, which I did not find elsewhere.)

2
  • Are you assuming each word is more than 10 characters length? I am testing this one but number words where it cuts off it varies on how many characters does it have. Jan 22, 2021 at 19:52
  • 1
    It inserts the 'read more' tag at the first space after 280 characters, so, yes, the number of words will vary depending on their length. Since I posted this, I found that WordPress shortcodes needed to be catered for; I have now updated the code in the answer to cover this.
    – Jake
    Jan 31, 2021 at 0:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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