Skip to content

Commit

Permalink
Add Steps component to reading-times.mdx (#8069)
Browse files Browse the repository at this point in the history
Co-authored-by: Houston (Bot) <108291165+astrobot-houston@users.noreply.github.com>
Co-authored-by: Sergio A. Arevalo Soria <sergio.alberto.arevalo.soria@nav.no>
Co-authored-by: Atharva <atharvapise19@gmail.com>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
  • Loading branch information
5 people committed May 2, 2024
1 parent fba6ebf commit 2d02c0a
Showing 1 changed file with 94 additions and 92 deletions.
186 changes: 94 additions & 92 deletions src/content/docs/en/recipes/reading-time.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,113 +4,115 @@ description: Build a remark plugin to add reading time to your Markdown or MDX f
i18nReady: true
type: recipe
---

import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro'
import { Steps } from '@astrojs/starlight/components';
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro';

Create a [remark plugin](https://github.com/remarkjs/remark) which adds a reading time property to the frontmatter of your Markdown or MDX files. Use this property to display the reading time for each page.

## Recipe

<Steps>
1. Install Helper Packages

Install these two helper packages:
- [`reading-time`](https://www.npmjs.com/package/reading-time) to calculate minutes read
- [`mdast-util-to-string`](https://www.npmjs.com/package/mdast-util-to-string) to extract all text from your markdown

<PackageManagerTabs>
<Fragment slot="npm">
```shell
npm install reading-time mdast-util-to-string
```
</Fragment>
<Fragment slot="pnpm">
```shell
pnpm add reading-time mdast-util-to-string
```
</Fragment>
<Fragment slot="yarn">
```shell
yarn add reading-time mdast-util-to-string
```
</Fragment>
</PackageManagerTabs>
Install these two helper packages:
- [`reading-time`](https://www.npmjs.com/package/reading-time) to calculate minutes read
- [`mdast-util-to-string`](https://www.npmjs.com/package/mdast-util-to-string) to extract all text from your markdown

<PackageManagerTabs>
<Fragment slot="npm">
```shell
npm install reading-time mdast-util-to-string
```
</Fragment>
<Fragment slot="pnpm">
```shell
pnpm add reading-time mdast-util-to-string
```
</Fragment>
<Fragment slot="yarn">
```shell
yarn add reading-time mdast-util-to-string
```
</Fragment>
</PackageManagerTabs>

2. Create a remark plugin.

This plugin uses 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.
```js title="remark-reading-time.mjs"
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);
// readingTime.text will give us minutes read as a friendly string,
// i.e. "3 min read"
data.astro.frontmatter.minutesRead = readingTime.text;
};
}
```
This plugin uses 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.
```js title="remark-reading-time.mjs"
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);
// readingTime.text will give us minutes read as a friendly string,
// i.e. "3 min read"
data.astro.frontmatter.minutesRead = readingTime.text;
};
}
```
3. Add the plugin to your config:
```js title="astro.config.mjs" "import { remarkReadingTime } from './remark-reading-time.mjs';" "remarkPlugins: [remarkReadingTime],"
import { defineConfig } from 'astro/config';
import { remarkReadingTime } from './remark-reading-time.mjs';
```js title="astro.config.mjs" "import { remarkReadingTime } from './remark-reading-time.mjs';" "remarkPlugins: [remarkReadingTime],"
import { defineConfig } from 'astro/config';
import { remarkReadingTime } from './remark-reading-time.mjs';
export default defineConfig({
markdown: {
remarkPlugins: [remarkReadingTime],
},
});
```
export default defineConfig({
markdown: {
remarkPlugins: [remarkReadingTime],
},
});
```
Now all Markdown documents will have a calculated `minutesRead` property in their frontmatter.
Now all Markdown documents will have a calculated `minutesRead` property in their frontmatter.
4. Display Reading Time
If your blog posts are stored in a [content collection](/en/guides/content-collections/), access the `remarkPluginFrontmatter` from the `entry.render()` function. Then, render `minutesRead` in your template wherever you would like it to appear.
```astro title="src/pages/posts/[slug].astro" "const { Content, remarkPluginFrontmatter } = await entry.render();" "<p>{remarkPluginFrontmatter.minutesRead}</p>"
---
import { CollectionEntry, getCollection } from 'astro:content';
export async function getStaticPaths() {
const blog = await getCollection('blog');
return blog.map(entry => ({
params: { slug: entry.slug },
props: { entry },
}));
}
const { entry } = Astro.props;
const { Content, remarkPluginFrontmatter } = await entry.render();
---
<html>
<head>...</head>
<body>
...
<p>{remarkPluginFrontmatter.minutesRead}</p>
...
</body>
</html>
```
If you're using a [Markdown layout](/en/guides/markdown-content/#markdown-and-mdx-pages), use the `minutesRead` frontmatter property from `Astro.props` in your layout template.

```astro title="src/layouts/BlogLayout.astro" "const { minutesRead } = Astro.props.frontmatter;" "<p>{minutesRead}</p>"
---
const { minutesRead } = Astro.props.frontmatter;
---
<html>
<head>...</head>
<body>
<p>{minutesRead}</p>
<slot />
</body>
</html>
```
If your blog posts are stored in a [content collection](/en/guides/content-collections/), access the `remarkPluginFrontmatter` from the `entry.render()` function. Then, render `minutesRead` in your template wherever you would like it to appear.
```astro title="src/pages/posts/[slug].astro" "const { Content, remarkPluginFrontmatter } = await entry.render();" "<p>{remarkPluginFrontmatter.minutesRead}</p>"
---
import { CollectionEntry, getCollection } from 'astro:content';
export async function getStaticPaths() {
const blog = await getCollection('blog');
return blog.map(entry => ({
params: { slug: entry.slug },
props: { entry },
}));
}
const { entry } = Astro.props;
const { Content, remarkPluginFrontmatter } = await entry.render();
---
<html>
<head>...</head>
<body>
...
<p>{remarkPluginFrontmatter.minutesRead}</p>
...
</body>
</html>
```
If you're using a [Markdown layout](/en/guides/markdown-content/#markdown-and-mdx-pages), use the `minutesRead` frontmatter property from `Astro.props` in your layout template.

```astro title="src/layouts/BlogLayout.astro" "const { minutesRead } = Astro.props.frontmatter;" "<p>{minutesRead}</p>"
---
const { minutesRead } = Astro.props.frontmatter;
---
<html>
<head>...</head>
<body>
<p>{minutesRead}</p>
<slot />
</body>
</html>
```
</Steps>

0 comments on commit 2d02c0a

Please sign in to comment.