メインコンテンツまでスキップ

Docusaurusの記事内でFront matterやmetadataの値を取得する方法

· 約7分
moritalous

Docksaurusでは記事をMarkdown形式で記述することができ、ヘッダー情報はFront matter で記述することができます。 記事の中でFront matterやmetadataの値を取得する方法を調査しました。

Front matterとは

Markdownの先頭部分に---で囲んだエリアにYaml形式で記述します。

index.md
---
id: doc-with-tags
title: A doc with tags
tags:
- Demo
- Getting started
---

## 見出し

ここが内容です。

このMarkdownはこのような表示となります。

image.png

環境

2023/01/07の最新バージョン2.2.0で確認しました。

記事の種類について

Docusaurusでは記事を投稿する方法として、以下の3種類があります。

  • Doc
  • Page
  • Blog

Front matterの値を取得する方法

ドキュメントに記載がありました。(リンク

index.md
  ---
id: doc-with-tags
title: A doc with tags
tags:
- Demo
- Getting started
---

## 見出し

ここが内容です。

+ <ul>
+ {Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
+ </ul>

images.png

もっと簡単に<div>{frontMatter.id}</div>で参照ができます。

tocとcontentTitleの値を取得する方法

Front matterと同じ方法で取得できる値としてtoccontentTitleもあります。

toc

index.md
---
id: doc-with-tags
title: A doc with tags
tags:
- Demo
- Getting started
---

## 見出し

ここが内容です。

# H1

H1

## H2

H2

### toc

<div>{JSON.stringify(toc, null, 2)}</div>

image.png

contentTitle

index.md
---
id: doc-with-tags
title: A doc with tags
tags:
- Demo
- Getting started
---

# タイトル(H1見出し)

## 見出し

ここが内容です。

### contentTitle

<div>{contentTitle}</div>

index.png

注記

contentTitleはMarkdown先頭にあるh1ヘッダーが対象になります。先頭にない場合はundefinedになります。

metadataの値を取得する方法

ドキュメントに記載はありませんが、metadataも同様の方法で取得可能です。

index.md
---
id: doc-with-tags
title: A doc with tags
tags:
- Demo
- Getting started
---

# タイトル

## 見出し

ここが内容です。

### metadata

<div>{JSON.stringify(metadata, null, 2)}</div>

image.png

Front matterで取得できるidtitleの他にもdescriptionsourcepermalinkなどもあります。frontMatterも含まれてますね。

JSON
{
"unversionedId": "test/doc-with-tags",
"id": "test/doc-with-tags",
"title": "A doc with tags",
"description": "見出し",
"source": "@site/docs/test/test/index.md",
"sourceDirName": "test",
"slug": "/test/",
"permalink": "/docs/test/test/",
"draft": false,
"tags": [
{
"label": "Demo",
"permalink": "/docs/test/tags/demo"
},
{
"label": "Getting started",
"permalink": "/docs/test/tags/getting-started"
}
],
"version": "current",
"frontMatter": {
"id": "doc-with-tags",
"title": "A doc with tags",
"tags": [
"Demo",
"Getting started"
]
},
"sidebar": "tutorialSidebar"
}

Front matterやmetadataの値を独自コンポーネントで使用する

独自コンポーネントの場合は直接frontMatterを操作することはできません。

docs/test/test/index.md
---
id: doc-with-tags
title: A doc with tags
tags:
- Demo
- Getting started
---

# タイトル

## 見出し

ここが内容です。


import MyComponent from '@site/src/components/Test'

<MyComponent />
src/components/Test/index.tsx
import React from 'react';


export default function MyComponent() {

return (
<>
<ul>
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
</ul>
<div>{frontMatter.id}</div>
<div>{JSON.stringify(toc, null, 2)}</div>
<div>{contentTitle}</div>
<div>{JSON.stringify(metadata, null, 2)}</div>
</>
)
}

image.png

独自コンポーネントの場合はuseDocというhookが用意されていますので、これを使用するとFront matterなどにアクセスすることが可能になります。

src/components/Test/index.tsx
import React from 'react';

import { useDoc } from '@docusaurus/theme-common/internal';


export default function MyComponent() {

const { metadata, frontMatter, toc, contentTitle } = useDoc()

return (
<>
<ul>
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
</ul>
<div>{frontMatter.id}</div>
<div>{JSON.stringify(toc, null, 2)}</div>
<div>{contentTitle}</div>
<div>{JSON.stringify(metadata, null, 2)}</div>
</>
)
}

image.png

うまくいきました。

ただ、残念なことにuseDocDoc形式の場合のみ利用可能です。

  • Page形式でuseDocを呼び出した場合

image.png

Blog形式の場合はuseDocの代わりにuseBlogPostを使用するとfrontMattermetadatatocは取得が可能です。(contentTitleは取得できませんでした。)

src/components/Test/index.tsx
import React from 'react';

import { useBlogPost } from '@docusaurus/theme-common/internal';


export default function MyComponent() {

const { metadata, frontMatter, toc, contentTitle } = useBlogPost()

console.log(frontMatter)

return (
<>
<ul>
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
</ul>
<div>{frontMatter.id}</div>
<div>{JSON.stringify(toc, null, 2)}</div>
<div>{contentTitle}</div>
<div>{JSON.stringify(metadata, null, 2)}</div>

<div>contentTitleのタイプ:{(typeof contentTitle)}</div>

</>
)
}

image.png

注記

Page形式の際の方法はわかりませんでした。

doc/page/blogで共通して使用できるFront matterやmetadataの値を使用する独自コンポーネントを作成する

作成しているコンテンツの形式を気にするのが面倒な場合は、Markdownからpropsとして渡すのが良いでしょう。

src/components/Test/index.tsx
  import React from 'react';

- import { useDoc, type DocContextValue } from '@docusaurus/theme-common/internal';

- export default function MyComponent() {
+ export default function MyComponent({ metadata, frontMatter, toc, contentTitle }) {

- const { metadata, frontMatter, toc, assets, contentTitle } = useDoc() as DocContextValue

return (
<>
<ul>
{Object.entries(frontMatter).map(([key, value]) => <li key={key}><b>{key}</b>: {value}</li>)}
</ul>
<div>{frontMatter.id}</div>
<div>{JSON.stringify(toc, null, 2)}</div>
<div>{contentTitle}</div>
<div>{JSON.stringify(metadata, null, 2)}</div>
</>
)
}
index.md(doc/page/blog共通)
  ---
id: doc-with-tags
title: A doc with tags
tags:
- Demo
- Getting started
---

# タイトル

## 見出し

ここが内容です。


import MyComponent from '@site/src/components/Test'

- <MyComponent />
+ <MyComponent
+ metadata={metadata}
+ frontMatter={frontMatter}
+ toc={toc}
+ contentTitle={contentTitle} />


  • Doc形式 image.png

  • Page形式 image.png

  • Blog形式 image.png

注記

metadataの値は形式ごとに異なります。