When migrating from WordPress to Astro, one encounters various challenges.
One is handling the WordPress “More” tag, which originates from the More Element in the WordPress Block Editor.
After converting the WordPress export to Markdown, you will find `<!– more –>` tags in your content. These tags serve as delimiters in WordPress, allowing you to define where the excerpt ends on listing pages.
The Challenge
Astro does not provide a built-in mechanism to handle these tags. I also could not find a suitable plugin that would manage this functionality.
My first approach was to use a Remark plugin like remark-excerpt. However, this did not work as expected. Instead of adding an Excerpt property to the frontmatter or to the data object of the content collection, it simply replaced the Content with the Excerpt.
Writing a custom Remark plugin proved challenging as well. While extracting the excerpt markdown is straightforward, rendering it to HTML is not. Since Astro does not expose its renderer (yet*), you would need to create your own renderer or use Astro’s internal `astrojs/markdown-remark`. Both approaches are rather hacky and not really recommended.
* There are ongoing discussions about making the renderer API public: Astro Roadmap Discussion #1094.
The Solution
The current best way to handle the WordPress More Tag in Astro is to split the rendered HTML content directly.
On the list page where you want to display the excerpt, you can map over the entries, split the rendered HTML at the <!--more--> tag, and add the excerpt to the return object:
const previewPosts = await Promise.all(
posts.map(async (post) => {
const fullHtml = post.rendered?.html || '';
const moreIndex = fullHtml.indexOf('<!--more-->');
const excerptHtml = moreIndex !== -1 ? fullHtml.slice(0, moreIndex) : fullHtml;
const hasMore = moreIndex !== -1;
return { post, hasMore, excerptHtml };
}),
);
{previewPosts.map(({ post, hasMore, Content }) => (
<div class="preview-content">
<Content />
</div>
{hasMore && <p class="read-more">Read more...</p>}
))}Code language: JavaScript (javascript)
Straightforward and effective :)