#add read time
16 messages · Page 1 of 1 (latest)
Hi @agile edge. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
To add reading time to a list of blog posts in Astro, you can follow these steps:
- Install the necessary helper packages. You will need
reading-timeto calculate the reading time andmdast-util-to-stringto extract all text from your markdown. You can install these packages using npm, pnpm, or Yarn:
npm install reading-time mdast-util-to-string
or
pnpm add reading-time mdast-util-to-string
or
yarn add reading-time mdast-util-to-string
(Source: Astro Documentation (https://docs.astro.build/en/recipes/reading-time/#recipe))
- Create a remark plugin. This plugin will use the
mdast-util-to-stringpackage to get the Markdown file’s text. This text is then passed to thereading-timepackage to calculate the reading time in minutes.
import getReadingTime from 'reading-time';
import { toString } from 'mdast-util-to-string';
export function remarkReadingTime() {
return function (tree, { data }) {
const textOnPage = toString(tree);
const readingTime = getReadingTime(textOnPage);
data.astro.frontmatter.minutesRead = readingTime.text;
};
}
(Source: Astro Documentation (https://docs.astro.build/en/recipes/reading-time/#recipe))
- Add the plugin to your Astro configuration:
import { defineConfig } from 'astro/config';
import { remarkReadingTime } from './remark-reading-time.mjs';
export default defineConfig({
markdown: {
remarkPlugins: [remarkReadingTime],
},
});
(Source: Astro Documentation (https://docs.astro.build/en/recipes/reading-time/#recipe))
- Now, all Markdown documents will have a calculated
minutesReadproperty in their frontmatter. You can display this property in your blog posts. If your blog posts are stored in a content collection, access theremarkPluginFrontmatterfrom theentry.render()function. Then, renderminutesReadin your template wherever you would like it to appear.
const { entry } = Astro.props;
const { Content, remarkPluginFrontmatter } = await entry.render();
And in your HTML:
<p>{remarkPluginFrontmatter.minutesRead}</p>
(Source: Astro Documentation (https://docs.astro.build/en/recipes/reading-time/#recipe))
If you’re using a Markdown layout, use the minutesRead frontmatter property from Astro.props in your layout template.
const { minutesRead } = Astro.props.frontmatter;
And in your HTML:
<p>{minutesRead}</p>
(Source: Astro Documentation (https://docs.astro.build/en/recipes/reading-time/#recipe))
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@agile edge kapa.ai is still learning and improving, please let us know how it did by reacting below
@grim sable this works on the slug but doesn’t work in a list of posts. How can I show the reading time on the lists of posts as well as on the slug?
Let me check the knowledge base for you. One moment! :books:
To display the reading time on a list of posts, you would need to ensure that the minutesRead property is accessible when you're mapping over your posts.
Here's an example of how you might display a list of posts with their reading times:
import { getCollection } from 'astro:content';
const blogEntries = await getCollection('blog');
And in your HTML:
<ul>
{blogEntries.map(blogPostEntry => (
<li>
<a href={`/my-blog-url/${blogPostEntry.slug}`}>{blogPostEntry.data.title}</a>
<p>Reading time: {blogPostEntry.data.frontmatter.minutesRead}</p>
<time datetime={blogPostEntry.data.publishedDate.toISOString()}>
{blogPostEntry.data.publishedDate.toDateString()}
</time>
</li>
))}
</ul>
In this example, blogPostEntry.data.frontmatter.minutesRead is used to access the reading time that was calculated and stored in the frontmatter of each post.
Please note that this assumes you have followed the previous steps to create and use the remarkReadingTime plugin, and that your blog posts are stored in a content collection.
(Source: Astro Documentation (https://docs.astro.build/en/guides/content-collections/#using-content-in-astro-templates))
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@agile edge kapa.ai is still learning and improving, please let us know how it did by reacting below
@grim sable this didn’t work. It says Cannot read properties of undefined (reading 'minutesRead')
Let me check the knowledge base for you. One moment! :books:
I'm sorry to hear that you're having trouble. The error message you're seeing typically means that the frontmatter object or the minutesRead property within it is not defined.
This could be due to a few reasons:
-
The
remarkReadingTimeplugin might not be correctly set up or might not be running as expected. Please ensure that you have followed the steps to create and use theremarkReadingTimeplugin correctly. -
The
minutesReadproperty might not be correctly set in the frontmatter of your posts. Please ensure that theminutesReadproperty is being correctly calculated and set in the frontmatter of each post. -
The structure of your data might be different than expected. Please ensure that the structure of your
blogPostEntryobjects matches the structure expected in the code.
Without more information about your setup and the exact code you're using, it's difficult to provide a more specific solution. However, I would recommend checking the above points to see if they help resolve the issue.
If you're still having trouble, you might find it helpful to refer to the Astro Documentation (https://docs.astro.build/) or to ask for help in the Astro GitHub Discussions (https://github.com/withastro/astro/discussions) or Astro Discord server (https://astro.build/chat).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@agile edge kapa.ai is still learning and improving, please let us know how it did by reacting below
@grim sable how can I change the default text string in the reading time plugin?
Let me check the knowledge base for you. One moment! :books:
To change the default text string in the reading-time plugin, you can pass an options object to the getReadingTime function. This object can include a wordPerMinute property to change the reading speed assumption (default is 200 words per minute), and a format function to customize the output string.
Here's an example of how you might customize the output string:
import getReadingTime from 'reading-time';
import { toString } from 'mdast-util-to-string';
export function remarkReadingTime() {
return function (tree, { data }) {
const textOnPage = toString(tree);
const readingTime = getReadingTime(textOnPage, {
format: function(time) {
let wordsPerMinute = time.words / (time.minutes || 1);
let timeStr = Math.ceil(time.minutes.toFixed(2));
return `${timeStr} minute read at ${wordsPerMinute.toFixed(2)} words per minute`;
}
});
data.astro.frontmatter.minutesRead = readingTime.text;
};
}
In this example, the format function is used to customize the output string to include the reading speed in words per minute.
Please note that this is just an example, and you can customize the format function to return any string you like based on the time object, which includes text, minutes, time, and words properties.