【@nuxt/content V2】Proseコンポーネント/MDC Syntaxで記事のコンテンツタイプ/スタイルをもっと自由に

やりたいこと

待ちに待った@nuxt/contentのVue3対応。contentがV2になって、ちょっとばかり以前とクセが違ってたりする中で、おそらく前にはなかったProseコードを活用してみたので、メモメモ。

@nuxt/contentについてを簡単に解説

.md形式を中心に、ルールにのっとってコンテンツを記載したファイルを作成することで簡易的にCMSとして活用できるNuxt用のモジュール。
ファイルの存在を確認して、テンプレートにコンテンツを表示したり、リストが作れたりとなにかと便利。

詳細は公式ドキュメントを確認。

Proseコンポーネント

まずは、あらかじめ@nuxt/content側で準備されているコンポーネント。 md形式で記載することで、自動でhtml変換してくれる。

heading要素やリスト、リンク等いろいろとあるけれど、 どんなものがあるのかは参照に記載のURLを見ることとして、

ここでメモメモしておきたいことは↓

[参照URLより]
To overwrite a prose component, create a component with the same name in your projectcomponents/content/directory (ex: components/content/ProseA.vue)

[訳]
Proseコンポーネントを上書きするには、components/content/ディレクトリに、同じ名前でコンポーネントを作ってね(例:components/content/ProseA.vue)

例えばスタイリングのために要素を付けたしたい等々ある場合は、

  • components/content/ProseH1.vue
  • components/content/ProseUl.vue
  • components/content/ProseBlockquote.vue

と、ファイルを作って、mdに記入しているコンテンツを挿入する部分に<slot>を活用した↓のような記載をすれば、デフォルトから変更した要素のコンポーネントを作ることができるよ、ってこと。

ProseH1.vue
<template>  <h1>    <span><slot /></span>  </h1></template>

MDC Syntax

MDC(MarkDown Components) っていうのを活用して、前述の既存のコンポーネント以外にも作成することができるよ、って雰囲気で説明いいのだろうか…。

例えばcomponents/content/card.vueっていうコンポーネントを作成して

card.vue
<template>  <div>    <slot />  </div></template>

コンテンツのmdファイルに↓のように書くと、card.vue<slot>部分にテキストが表示される。

article.md
::cardcardコンポーネントに記載するコンテンツ::

記事(mdファイル)のbody部分に↓を書いて、対応するコンポーネントを作成!これを覚えておこう。

::コンポーネント名コンテンツ::

YAML method

YAMLを混ぜ込むことで、もっと活用の幅が広がるよ、ということで、前述のcardコンポーネントを拡張してみる。

まずはコンポーネントの拡張。definePropsすると、項目を定義できる。そして、VueのPropsデータとしてテンプレートに埋め込み。

card.vue
<template>  <div>    <div><img :src="image"></div>    <div>{{title}}</div>    <div><slot /></div>  </div></template><script setup>defineProps({  title: {    type: String,    default: ''  },  image: {    type: String,    default: ''  }})</script>

コンテンツの方は---で囲んだ内側にYAMLを書くとコンポーネントにPropsとして渡すことができる。

article.md
::card---title: コンポーネントのタイトルimage: 画像のURL---コンポーネントの本文とか、ボディ要素的な。::

かんた~ん!

Codeブロック

前バージョンの名残でわかるだろ、ってことなのか、記載がなくてちょっと悩んだのでメモメモ。

デフォルトのCodeProseコンポーネントにはファイル名の表示がなく、追加したいのだけど、 md形式で記載すると、そのHTML変換が<pre><code>なので、内側に書くのも違う…

解決方法は↓

article.md
---LangType [filename.html]hogehoge---
ProseCode
<template>  <div class="code-box">    <span>{{filename}}</span>    <slot />  </div></template><script setup>defineProps({  filename: {    type: String,    default: ''  }})</script>

---LangType [ファイル名]と記載することで、filenamepropとして取得できた!

おまけ:コードハイライト

以前のバージョンでは、PrismJSを採用していたみたいなのだけど、Shikiに変更。
設定の仕方もシンプルにnuxt.config.tsにテーマ名をちょっと追記するだけ。

nuxt.config.ts
export default defineNuxtConfig({  content: {    highlight: {      theme: 'dracula-soft'    }  }})

おわり

シンプルながら多機能に使える@nuxt/content。コンポーネントの拡張についてだけでも、まだまだできることあるっぽい。またなにかしたくなったら調べよう~