このシリーズでは、ドキュメントサイトをつくりながら Docusaurus の使い方を説明しています。

前回「ドキュメント編」では、ドキュメントページの追加とサイドバーのカスタマイズまで進めました。今回は Markdown や MDX の機能を見ていきます。

なお、Docusaurus の Markdown の詳細は、以下の公式ドキュメントから確認できます。

本記事の完成後のデータ一式は以下の GitHub リポジトリにアップしています。

サンプルページの作成

見出し「サンプルページの作成」

Markdown / MDX の機能を試していくにあたり、まずサンプル用のページを docs/markdown.mdx というファイル名で追加します。

なお、Docusaurus では、拡張子が .md でも MDX として処理されます。

今回は、サンプルページはビルドには含めずに開発時のみに使用できるようにします。そのために、Front Matter に draft: true と指定して、下書き状態とします。

docs/markdown.mdx
---
draft: true
---

# Markdown サンプル

追加したサンプルページへのリンクをサイドバー(sidebars.js)にも反映します。

sidebars.js
const sidebars = {
  tutorialSidebar: [
    {
      type: 'doc',
      id: 'index',
    },
    {
      type: 'category',
      label: '固定ページ',
      link: {
        type: 'generated-index',
        title: '固定ページ',
        slug: '/pages',
      },
      items: [
        'pages/home',
        'pages/services',
      ]
    },
    {
      type: 'doc',
      id: 'information',
    },
    /* サンプルページを追加 */
    {
      type: 'doc',
      id: 'markdown',
    },
  ],
};

module.exports = sidebars;

あらためて Markdown とは、シンプルなテキストで文書構造を表現することができる軽量のマークアップ言語です。ツールを介して HTML 形式などへの変換が可能です。

Markdown をめぐる仕様の変遷

見出し「Markdown をめぐる仕様の変遷」

Markdown は「読みやすく」「書きやすい」特徴を持った文書を、適切な XHTML または HTML に変換できるフォーマットとして、John Gruber 氏とその協力者である Aaron Swartz 氏によって 2004 年に考案されました。

その後、多くのサービスで使われるようになる Markdown ですが、明確な仕様が存在しなかったため、実装によって異なる解釈が生まれてしまう曖昧さが問題となりました。

この問題を解決するために、2014 年以降、CommonMark プロジェクトにより仕様化が進められました。現在も、この CommonMark の仕様をベースに、独自の記法や拡張機能を取り入れたいくつものバリエーションが生まれています。

GitHub は、2009 年より Markdown から派生した独自の GitHub Flavored Markdown(GFM)を導入していましたが、2017 年に CommonMark の上位互換として改めて仕様化されました。

Docusaurus では Markdown 内で JSX 構文で作られたコンポーネントを使用できる、MDX をサポートしています。

少しややこしいのですが、この MDX は CommonMark の仕様をベースとしており、GFM の拡張機能は remark のプラグイン経由で使用できます。Docusaurus では、この GFM の拡張機能が使える状態になっています。

ここで一旦、Docusaurus での Markdown 機能の前提をまとめます。

  • MDX をサポートしており、JSX 構文で作られたコンポーネントが使用できる
  • .md.mdx どちらの拡張子でも MDX として処理される
  • GFM の拡張機能を使用できる(remark プラグイン経由)

GitHub Flavored Markdown(GFM)

見出し「GitHub Flavored Markdown(GFM)」

GitHub をはじめ、さまざまなサービスで使われているため、なじみ深いと思いますが、以下に GFM の基本的な記法をピックアップします(折りたたんでいます)。

GFM の基本的な記法
docs/example/markdown.mdx
# 見出しレベル 1
## 見出しレベル 2
### 見出しレベル 3
#### 見出しレベル 4
##### 見出しレベル 5
###### 見出しレベル 6
docs/example/markdown.mdx
![代替テキスト](/img/docusaurus.png)

画像は、以下の参照形式にも対応しています。

docs/example/markdown.mdx
![代替テキスト][1]

[1]: /img/docusaurus.png

参照形式は URL が長いときなどに、記述箇所を分けることで可読性を高めることができますが、ファイル内で参照する ID の値を一意にしなければならない点に留意する必要があります。

Markdown の記法で画像を指定した場合、Docusaurus では loading="lazy"widthheight が自動的に付与されます。パフォーマンスの向上が見込める反面、ファーストビュー(Above the fold)に配置される画像の LCP を悪化させる要因にもなるので注意が必要です。

docs/example/markdown.mdx
次の空行までのテキストのまとまりが段落テキストとして扱われます。

行末の半角スペース 2 つで  
改行できます。

**強調テキスト**(strong)

*強調テキスト*(em)

~~取り消し線~~(del)

取り消し線は、GFM の拡張機能です。

docs/example/markdown.mdx
[Markdown Features | Docusaurus](https://docusaurus.io/docs/markdown-features)

リンクは、以下の参照形式にも対応しています。

docs/example/markdown.mdx
[Markdown Features | Docusaurus][2]

[2]: https://docusaurus.io/docs/markdown-features

画像同様に、参照形式を使用することで文書の可読性を高めることができますが、ID の値をユニークにしなければならない点に留意する必要があります。

GFM の拡張機能として、以下のような URL 形式やメール形式のテキストは、自動的にリンクが付与されますが、なるべく使用は控えたほうがよいでしょう。

docs/example/markdown.mdx
www.example.com  
https://example.com  
[email protected]
docs/example/markdown.mdx
- リスト項目
- リスト項目
    - リスト項目
- リスト項目

1. リスト項目
2. リスト項目
3. リスト項目
docs/example/markdown.mdx
以下は `sidebars.js` の例です。

```js
const sidebars = {
  tutorialSidebar: [
    {
      type: 'autogenerated',
      dirName: '.'
    }
  ],
};

module.exports = sidebars;
```
docs/example/markdown.mdx
> The power of the Web is in its universality.  
> Access by everyone regardless of disability is an essential aspect.

— Tim Berners-Lee, W3C Director and inventor of the World Wide Web

タスクリストは GFM の拡張機能です。

docs/example/markdown.mdx
- [x] タスク 1
- [ ] タスク 2
- [x] タスク 3

表は GFM の拡張機能です。

docs/example/markdown.mdx
| 見出しセル | 見出しセル |
| --- | --- |
| データセル | データセル |
| データセル | データセル |
| データセル | データセル |

| 左揃え | 中央揃え | 右揃え |
| :--- | :---: | ---: |
| foo | foo | foo |
| foo bar | foo bar | foo bar |
| foo bar baz | foo bar baz | foo bar baz |

列方向の見出しセル要素(tbody > th)や、colspanrowspan でのセルの結合は表現できないので、その場合は HTML で記述する必要があります。

続いて、そのほかの拡張機能を見ていきます。

コードブロックは、GFM の記法に加えて Docusaurus 独自の機能があります。

コードブロック開始位置の ``` の後ろの半角スペースに続けて、title="" でタイトルを明示することができます。

docs/example/markdown.mdx
```js title="sidebars.js"
const sidebars = {
  tutorialSidebar: [
    {
      type: 'autogenerated',
      dirName: '.'
    }
  ],
};

module.exports = sidebars;
```
コードブロックのスクリーンショット
コードブロックの上にタイトルが表示される

以下のコメントで特定の行をハイライト表示できます。

  • // highlight-next-line : 次の行をハイライト
  • // highlight-start// highlight-end : ハイライトの範囲を指定
docs/example/markdown.mdx
```js
const sidebars = {
  tutorialSidebar: [
    {
      type: 'doc',
      // highlight-next-line
      id: 'index',
    },
    {
      type: 'doc',
      id: 'information',
    },
    // highlight-start
    {
      type: 'doc',
      id: 'markdown',
    },
    // highlight-end
  ],
};

module.exports = sidebars;
```
コードブロックのスクリーンショット
コメントを指定した範囲がハイライト表示される

これらの特殊なコメントは「Magic comments」と呼ばれ、Docusaurus ではユーザ独自のコメントのルールとスタイルを追加することもできます。

なお、以下のようにコードの行番号 {5,11-14} を指定してハイライトさせることもできますが、コード全体の行数が変わると位置が変わるリスクがあるので避けたほうがよいでしょう。

docs/example/markdown.mdx
```js {5,11-14}
const sidebars = {
  tutorialSidebar: [
    {
      type: 'doc',
      id: 'index',
    },
    {
      type: 'doc',
      id: 'information',
    },
    {
      type: 'doc',
      id: 'markdown',
    },
  ],
};

module.exports = sidebars;
```

以下のように showLineNumbers を指定すると行番号を表示できます。

docs/example/markdown.mdx
```js showLineNumbers
const sidebars = {
  tutorialSidebar: [
    {
      type: 'doc',
      id: 'index',
    },
    {
      type: 'doc',
      id: 'information',
    },
    {
      type: 'doc',
      id: 'markdown',
    },
  ],
};

module.exports = sidebars;
```
コードブロックのスクリーンショット
コードブロックの左に行番号が表示される

Docusaurus npm2yarn remark plugin

見出し「Docusaurus npm2yarn remark plugin」

Docusaurus npm2yarn remark plugin は、npm のコマンドを指定するだけで、Yarn と pnpm のコマンドをタブ形式で生成してくれるプラグインです。

以下のコマンドでプラグインをインストールします。

Docusaurus npm2yarn remark plugin をインストールするコマンド
npm install @docusaurus/remark-plugin-npm2yarn

docusaurus.config.jspresets に、プラグインの設定を追加します。

docusaurus.config.js
// ...
const config = {
  // ...
  presets: [
    [
      'classic',
      /** @type {import('@docusaurus/preset-classic').Options} */
      ({
        docs: {
          routeBasePath: '/',
          sidebarPath: require.resolve('./sidebars.js'),
          /* プラグインの設定を追加 */
          remarkPlugins: [
            [require('@docusaurus/remark-plugin-npm2yarn'), {sync: true}],
          ],
        },
        // ...
      }),
    ],
  ],
};

module.exports = config;

以下のように、コードブロックに npm2yarn を指定すると有効になります。

docs/example/markdown.mdx
```bash npm2yarn
npm install @docusaurus/remark-plugin-npm2yarn
```

ドキュメントのインデックスページ(docs/index.md)のコードブロックに npm2yarn を追加して表示を確認してみましょう。

docs/index.md
データを取得したディレクトリに移動して、npm パッケージをインストールします。

```bash npm2yarn
npm install
```

## TinaCMS の起動

以下のコマンドで TinaCMS が起動します。

```bash npm2yarn
npm start
```
ドキュメントのインデックスページのスクリーンショット。コードブロックの上にタブ「npm」「Yarn」「pnpm」が追加され「Yarn」が選択されている状態
「npm」「Yarn」「pnpm」でタブが分かれ、それぞれのコマンドが表示される

Docusaurus では、折りたたみ要素(アコーディオン)のスタイルが用意されていますが、HTML タグ(<details><summary>)で記述する必要があります。

docs/example/markdown.mdx
<details>
  <summary>アコーディオン</summary>
  <p><code>&lt;details&gt;</code> と <code>&lt;summary&gt;</code> のスタイルが用意されています。</p>
</details>

以下のように、折りたたみ要素のスタイルが適用されます。

折りたたみ要素のスクリーンショット

Docusaurus では、注記や警告などを表現する「Admonitions」と呼ばれる要素を使用できます。この機能は remark プラグインによって実装されています。

対象箇所を ::: から ::: までで囲い、開始位置にキーワードを指定します。

docs/example/markdown.mdx
:::note

[Docusaurus](#) は、*React ベース*でつくられた**ドキュメントサイト**に特化した `SSG` です。

:::

:::tip

[Docusaurus](#) は、*React ベース*でつくられた**ドキュメントサイト**に特化した `SSG` です。

:::

:::info

[Docusaurus](#) は、*React ベース*でつくられた**ドキュメントサイト**に特化した `SSG` です。

:::

:::caution

[Docusaurus](#) は、*React ベース*でつくられた**ドキュメントサイト**に特化した `SSG` です。

:::

:::danger

[Docusaurus](#) は、*React ベース*でつくられた**ドキュメントサイト**に特化した `SSG` です。

:::

日本語にローカライズされた状態でのテキストラベルは以下のとおりです。

キーワードテキストラベル
note注記
tipヒント
info備考
caution注意
danger危険

指定したキーワードによって、テキストラベル、アイコン、カラーが変わります。

Admonitions のスクリーンショット

キーワードの後ろの半角スペースに続けて、文字列を指定することでテキストラベルを変更することができます。

docs/example/markdown.mdx
:::note メモ

[Docusaurus](#) は、*React ベース*でつくられた**ドキュメントサイト**に特化した `SSG` です。

:::

なお、詳しい説明は省きますが、docusaurus write-translations コマンドを実行することで翻訳データ(JSON ファイル)を取得することができます。

この JSON ファイルの内容を変更することで、Admonitions の「注記」や「ヒント」のような、デフォルトのテキストラベルを変更することができます。

脚注は remark のプラグイン経由で実装されています。

docs/example/markdown.mdx
脚注[^1]を加えることができます[^2]

[^1]: 脚注の例です。
[^2]: **脚注内***一部*[`Markdown` 記法](#)を使用できます。

Docusaurus では、タブ切り替えのコンポーネントが用意されています。

docs/example/markdown.mdx
<Tabs>
  <TabItem value="html" label="HTML" default>
    HTML は HyperText Markup Language の略語です。
  </TabItem>
  <TabItem value="css" label="CSS">
    CSS は Cascading Style Sheets の略語です。
  </TabItem>
  <TabItem value="svg" label="SVG">
    SVG は Scalable Vector Graphics の略語です。
  </TabItem>
</Tabs>

本来は TabsTabItem をインポートして使用するのですが、前述の Docusaurus npm2yarn remark plugin を有効にしている状態では、明示的にインポートしなくても使用できます。

groupId 属性の値をそろえることで、タブの切り替えを同期させることができます。

docs/example/markdown.mdx
<Tabs groupId="operating-systems">
  <TabItem value="win" label="Windows">
    <b>Ctrl + C</b> で選択したテキストをコピーできます。
  </TabItem>
  <TabItem value="mac" label="macOS">
    <b>Command + C</b> で選択したテキストをコピーできます。
  </TabItem>
</Tabs>

<Tabs groupId="operating-systems">
  <TabItem value="win" label="Windows">
    <b>Ctrl + V</b> でコピーしたテキストをペーストできます。
  </TabItem>
  <TabItem value="mac" label="macOS">
    <b>Command + V</b> でコピーしたテキストをペーストできます。
  </TabItem>
</Tabs>

そのほかにも、スタイルを変更したり、クエリ文字列を指定することもできます。詳しくは公式ドキュメントをご確認ください。

カスタムコンポーネント

見出し「カスタムコンポーネント」

独自に作成した React コンポーネントを読み込むこともできます。

例として、テキストをマーカー風のスタイルで強調するカスタムコンポーネントを src/components/Marker.js というファイル名で作成します。

このコンポーネントは color 属性でマーカーのカラーを変更できます。

src/components/Marker.js
import React from 'react';

export default function Marker({children, color = 'greenyellow'}) {
  return (
    <em
      style={{
        background: `linear-gradient(to top, transparent 0, ${color} 0, ${color} 0.3em, transparent 0)`,
        fontSize: '120%',
        fontWeight: 'bold',
        fontStyle: 'normal',
      }}
    >
      {children}
    </em>
  );
}

MDX ファイルでインポートしてコンポーネントを使用します。

docs/example/markdown.mdx
import Marker from '@site/src/components/Marker';

HTML は <Marker>HyperText Markup Language</Marker> の略語です。

CSS は <Marker color="cyan">Cascading Style Sheets</Marker> の略語です。

SVG は <Marker color="pink">Scalable Vector Graphics</Marker> の略語です。

以下のように、<Marker> コンポーネントが有効になります。

カスタムコンポーネントのスクリーンショット

カスタムコンポーネントをグローバルなコンポーネントとして設定することも可能です。

src/theme/MDXComponents.js を新規作成し、以下のように Marker を追加します。

src/theme/MDXComponents.js
import MDXComponents from '@theme-original/MDXComponents';
import Marker from '@site/src/components/Marker';

export default {
  ...MDXComponents,
  Marker,
};

これで <Marker> コンポーネントがグローバルスコープになったので、インポートせずに使用することができます。

docs/example/markdown.mdx
HTML は <Marker>HyperText Markup Language</Marker> の略語です。

CSS は <Marker color="cyan">Cascading Style Sheets</Marker> の略語です。

SVG は <Marker color="pink">Scalable Vector Graphics</Marker> の略語です。

Docusaurus の Markdown は、このほかにもさまざまな機能がありますが、基本的な使い方としてはこんなところでしょうか。

次回は、ブログの機能を見ていきます。