#add read time

16 messages · Page 1 of 1 (latest)

agile edge
#

How can I add reading time to a list of blog posts?

grim sableBOT
#

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:

  1. Install the necessary helper packages. You will need reading-time to calculate the reading time and mdast-util-to-string to 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))

  1. Create a remark plugin. This plugin will use the mdast-util-to-string package to get the Markdown file’s text. This text is then passed to the reading-time package 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))

  1. 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))

#
  1. Now, all Markdown documents will have a calculated minutesRead property in their frontmatter. You can display this property in your blog posts. If your blog posts are stored in a content collection, access the remarkPluginFrontmatter from the entry.render() function. Then, render minutesRead in 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

agile edge
#

@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?

grim sableBOT
#

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

agile edge
#

@grim sable this didn’t work. It says Cannot read properties of undefined (reading 'minutesRead')

grim sableBOT
#

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:

  1. The remarkReadingTime plugin 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 the remarkReadingTime plugin correctly.

  2. The minutesRead property might not be correctly set in the frontmatter of your posts. Please ensure that the minutesRead property is being correctly calculated and set in the frontmatter of each post.

  3. The structure of your data might be different than expected. Please ensure that the structure of your blogPostEntry objects 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

agile edge
#

@grim sable how can I change the default text string in the reading time plugin?

grim sableBOT
#

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.

For more information about the reading-time package and the options you can pass to the getReadingTime function, you can refer to the reading-time package documentation (https://www.npmjs.com/package/reading-time).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: