Posted November 13th, 2006 @ 02:13pm by Erik J. Barzeski
get_the_content() function is responsible for, among other things, splitting up WordPress posts at the <!--more--> delimiter. It creates HTML that looks like this:
<p>Last paragraph of main entry<br /><a href="http://permalink">ReadMoreText</a></p>
The optional parameters (there are three, but only two work in WP 2.0) allow you to change the "ReadMoreText" in the example output above. The problem? Not only is the link missing a
title, but the text is all you can control.
WordPress' built-in "wpautop" function controls how posts are formatted with
<br /> tags. A single line break gets a break and double breaks - two line ending characters - are wrapped in paragraph tags. When you submit a post from nearly any third-party blogging tool (like) Ecto, it submits both an "entry body" and "extended entry." WordPress converts these to a format matching this:
When it later comes time for
get_the_content(), the function dutifully
explode()s on the
<!--more-->, leaving a trailing "\n" in the body and one at the beginning of the extended entry3. Next, it puts the title-less
<a href=""> in4:
$output .= ' <a href="'. get_permalink() . "#more-$id\">$more_link_text</a>";
Not only are links created without a title, but this approach is less than ideal for a couple of reasons:
- People who want to put "read more…" links on the same line as their last sentence cannot because the "wpautop" inserts a
- People who want their "Read More…" links in their own paragraph can do so, but the output is ugly HTML.
As I said above, only "ReadMoreText" can be replaced. The
the_content() function will happily accept text like this:
the_content('</p><p class="readmorelink">Read More');
Unfortunately, that does just what you'd expect:
<p>Last paragraph of main entry<br /><a href="http://permalink"></p><p class="readmorelink">Read More</a></p>
In this case, the anchor tag spans across paragraphs. Ick. If you're not afraid of modifying core WordPress files (in this case,
/wp-includes/template-functions-post.php), you can do something like this:
$output .= '</p><p class="readmorelink"><a href="'. get_permalink() . "#more-$id\" title=\"".the_title('','',false)."\">$more_link_text</a>";
That produces HTML that resembles this:
<p>Last paragraph of main entry.</p>
<p class="readmorelink"><a href="http://permalink#more-xxxx" title="Title Here">Read More</a></p>
That's acceptable. If you want your "read more" links in the same paragraph as the final paragraph of your entry body, you'll want to employ this change instead:
$output .= ' <span class="readmorelink"><a href="'. get_permalink() . "#more-$id\" title=\"".the_title('','',false)."\">$more_link_text</a></span>";
$output .= ' <a href="'. get_permalink() . "#more-$id\" title=\"".the_title('','',false)."\" class=\"readmorelink\">$more_link_text</a></span>";
Unfortunately, without testing for and removing the final two "\n" characters at the end and beginning of the entry body and extended entry respectively, you'll get extra
<br /> tags. In this example, your link would be on a different line (but within the same set of
<p> tags.). You can remove (actually, move) the links like this:
Change this (line 90):
$output .= $teaser;
$output .= ("\n" == substr($teaser, -1, 1)) ? substr($teaser, 0, -1) : $teaser;
And change this (line 93):
$output .= '<a id="more-'.$id.'"></a>'.$content;
$output .= '<a id="more-'.$id.'"></a>' . "\n".$content;
That performs a ternary test on the raw, un-
wpautoped text to remove the trailing "\n" characters from the entry body and to double them up in the extended entry. Because this eliminates the problem noted in the third footnote, I've left this code in my copy even though I use the paragraph version of the "read more" link5.
What To Do About It?
I'm too new to WordPress to know whether this function can be modified via a plugin. It's not a "pluggable" function, so that rules that out. I'm not keen on modifying core files, either.
In the end, and to maintain backwards compatibility, I think the best approach to solving this problem would be for WordPress to alter the
the_content() function. Currently, as I said, it takes three variables. It should take four:
<?php the_content('more_link_text', strip_teaser, 'more_file', 'link_type');?>
The additional "link_type" variable could be set to false by default and WordPress would continue to create links as it does now. If this is set to "endp" it could create the link at the end of the "teaser" or "entry body" paragraph. If it's set to "newp" then WordPress would wrap the link and text in its own paragraph. Perhaps "endp:class" and "newp:class" could be used to specify the class the
p tags would use6.
I think the function should also be modified to add the
title attribute to links and to remove the trailing "\n" in every instance, as it offers nothing of benefit.
I'm not sure where to file such a bug report within WordPress, so I'll post this and ask around. The WordPress folks are free, naturally, to take my suggestions, take any of the code above, and use any of it without restriction.
- Line 54 of
/wp-includes/template-functions-post.phpin version 2.0.5.↩
- Eight lines down in the same file.↩
- This is significant because WordPress later double-
<br />s these "\n"s with an
<a href="more"></a>link in between. In other words, the paragraph break across your entry body and extended entry aren't true paragraph breaks, but two line breaks↩
- Line 95 of
/wp-includes/template-functions-post.phpin WP 2.0.5.↩
- The only side effect? That your
<a href="#more-xxxx">link appears in the final paragraph of the entry body on the permalink page. That is no worse, if you think about it, than not actually having a separate paragraph across that boundary.↩
- I'm not familiar enough with WordPress's internal code formatting to know if this is a valid method of formatting, but I'm trying to point out how the functionality could be improved, not necessarily the exact way in which the code should be written.↩