Nuxt Contentでドキュメント用のページを作成する

spiral notebooks NuxtJS
Photo by Pixabay on Pexels.com
この記事は約9分で読めます。

 はじめに

最近、個人的にNuxt3を使って趣味の範疇でWebサービスを作ったりしています。サイト内のドキュメントをマークダウン形式でカジュアルに書きたいと思いNuxt Contentを触ることがあったので、備忘録のためにメモに残しておきたいと思います。

Nuxt Content

Nuxt ContentのGitHubの評価は以下のとおりとなっています。

Package Name GitHub Stars GitHub Link
@nuxt/content 2.9k https://github.com/nuxt/content

(2024/2/11時点、日本時間)

Nuxt Contentは、MarkdownやJSON、YAML、CSVで書かれたドキュメントをページコンテンツとして表示することができるNuxt上で動作するライブラリです。Nuxt Contentは、v1.0.0がMay 22、2020となっており本記事執筆時点で4年弱となるプロジェクトとなっています。コミット履歴を見ると現在もアクティブに開発されていることが分かります。NuxtのOfficialモジュールでもあります。

使用方法

ここからは、Nuxt Contentの使用方法について見ていきます。

最初に、サンプルを動かす環境について記述します。

環境

  • mac OS Catalina 10.15.7
  • NodeJS 20.11.0
  • nuxt@3.10.1
  • @nuxt/content@2.11.0

インストール

まずは、テンプレートプロジェクトを作成しVSCodeでプロジェクトを開きます。

構成

プロジェクトを開くとサンプルドキュメントが2ファイルあることが分かります。以下のような構成になっています。以下関連のあるディレクトリにのみフォーカスします。

app.vue

nuxt.config.ts

pages/[...slug].vue

テンプレートプロジェクトを起動

サンプルプロジェクトを起動すると、以下のようにindexページとaboutページを見ることができます。ページにアクセスする際には拡張子は不要です。

 http://localhost:3000

Nuxt Contentでは、contentというディレクトリにドキュメントを格納する規約になっています。これはconfiguratioinで変えることも可能です。

テンプレートの例では、pagesでcatch-all routeの設定をしています。全てのページアクセスをcatch-all routeのページコンポーネントが処理し、そしてContentDocコンポーネントが処理します。ContentDocコンポーネントは、ContentQueryとContentRendererコンポーネントを内部で呼び出し、要求されたページリクエストに対する結果を返します。

ContentDocコンポーネント

最もベーシックであろうContentDocコンポーネントを見ていきます。

404のページ処理(#not-found)

ContentDocのnot-foundスロットが使えます。以下のようにするとページが見つからない場合の表示を変えることができます。

pages/[...slug].vue

空ページの表示(#empty)

ContentDocのemptyスロットで可能です。ドキュメントが空の場合にデフォルト表示を設定できます。

pages/[...slug].vue

独自のHTMLの定義

デフォルトスロットで可能です。

pages/[...slug].vue

content/test.md

Props
path

指定したパスのドキュメントを返します。デフォルトは、$route.pathとなっているためpathのドキュメントが動的に返るようになっています。以下ではabout.mdに固定しています。

pages/[...slug].vue

excerpt

サマリの表示をするか否かを設定します。

content/test.md

pages/[...slug].vue

more以降が表示されません。falseにすると表示されます。

query

content/test.md

pages/[...slug].vue

queryContentの条件を指定します。条件式はmongo queryを参考にします。

arrow-right
Learn about the query and projection operators in MongoDB. These query selectors, projection operators, and miscellaneou...
head

falseにするとuseHead Composableとのバインディングがされず、例えばtitleが紐付けされなくなります。

ドキュメントの順序

ドキュメントは、ファイル名の先頭に数値.とつけることで、優先順位付けができます。

ドキュメントに対するクエリでsortすることができます。

YAML、JSON、CSV

YAML、JSON、CSVについてはクエリの結果を受け取れます。YAMLで試してみます。

content/aa.yml

ContentDocコンポーネントの出力は以下のようになりました。ContentDocが呼び出しているContentRendererコンポーネントは、ContentRendererMarkdownを使用します。パースした結果のASTがrendererの形式にマッチしていない場合、fallbackされjson形式の文字列が返ってくるようです。

画像の表示

画像等はpublicディレクトリの下に置けばマークダウンの形式で参照できます。

content/test.md

コードハイライト

nuxt.config.ts

content/test.md

以下のようにコードハイライトされました。

日本語ファイル名

_path属性を定義することで表示させることができました。_path属性を指定しないと404になってしまいます。

ページのデザイン

マークダウンのドキュメントではコンポーネント呼び出しが可能です。アクションやデザインを独自に適用したい場合に使えます。

また、Prose Componentsというマークダウン形式が変換され適用されるコンポーネントを上書きすることでも振る舞いを返ることができます。

Prose Components – Nuxt Content

H1タグを上書きして見ます。

content/test.md

components/content/ProseH1.vue

公式のものを複製し「タイトル:」という文字を先頭につけるようにしています。

referenced by mdc/src/runtime/components/prose/ProseH1.vue at main · nuxt-modules/mdc (github.com)

pages/[...slug].vue

ついでに、ProsePreコンポーネントも上書きし、preタグの前にも「上書き」という文字列をつけています。

上書き用のコンポーネントが動作していることを確認できました。

特定のディレクトリをドキュメント用のページ構成にする

テンプレートプロジェクトの例ではpagesの直下をcatch-all routeとしましたが、manualやexamples、docsのようなディレクトリ名にマッチする場合だけドキュメントとした場合は、pages/examples/[...slug].vueのようにすれば可能です。ドキュメント側は、content/examples/1.introduction.md のようにします。

アプリケーショとマニュアルページを1つのプロジェクトで一元管理ができるため便利です。/docsや/blog、/newsのように目的に合わせたページを作成し、それぞれレイアウトを変えることもできるでしょう。

pages/blog/[...slug].vue

Document-driven mode

マークダウンベースのWebサイト運用のための機能で、本モードを有効にすると、contentディレクトリの下にドキュメント置くだけですぐにドキュメントページを作成できます。本記事の執筆時点ではexperimental featureとなっています。

document-driven modeは、デフォルトでcatch-all routeページをinjectしてくれます。そのため、自分でpagesの下にcatch-all routeのページコンポーネントを設置する必要がありません。また、ドキュメントごとにlayout属性を定義できるようになり、ドキュメントごとにレイアウトを変えることができます。

プロジェクト全部をマークダウンベースのWebサイトとするようなケースで便利な機能ではないでしょうか。

 まとめ

Nuxt Contentを使ってマークダウン形式のドキュメントをWebページで表示する方法を見てきました。コンテンツはコンポーネントやCSSを定義して調整する必要がありますが、セットアップも容易でアプリケーション内にサクッとマニュアルページのようなドキュメントを組み込むことができます。

今回は、一部の機能の使用例について記載しました。他にも便利なAPIが提供されているため、機会があればまた記事にあげたいと思います。

参考リンク

コメント

タイトルとURLをコピーしました