コンテンツにスキップ

@astrojs/ markdoc

このAstroインテグレーションは、Markdocを使用してコンポーネント、ページ、およびコンテンツコレクションのエントリを作成できるようにします。

Markdocを使用すると、AstroコンポーネントでMarkdownを強化できます。Markdocで作成された既存のコンテンツがある場合、このインテグレーションを使用すると、コンテンツコレクションを使用してそれらのファイルをAstroプロジェクトに持ち込むことができます。

Astroには、公式インテグレーションのセットアップを自動化するためのastro addコマンドが含まれています。もしよろしければ、手動でインテグレーションをインストールすることもできます。

新しいターミナルウィンドウで次のいずれかのコマンドを実行します。

ターミナルウィンドウ
npx astro add markdoc

問題が発生した場合は、GitHubで報告してください。そして、以下の手動インストール手順を試してください。

まず、@astrojs/markdocパッケージをインストールします。

ターミナルウィンドウ
npm install @astrojs/markdoc

次に、integrationsプロパティを使用して、インテグレーションをastro.config.*ファイルに適用します。

astro.config.mjs
import { defineConfig } from 'astro/config';
import markdoc from '@astrojs/markdoc';
export default defineConfig({
// ...
integrations: [markdoc()],
});

VS Codeを使用している場合は、構成されたタグの構文ハイライトとオートコンプリートを含む公式のMarkdoc言語拡張機能があります。詳細については、GitHubの言語サーバーを参照してください。

拡張機能をセットアップするには、プロジェクトのルートにmarkdoc.config.jsonファイルを作成し、次の内容を含めます。

markdoc.config.json
[
{
"id": "my-site",
"path": "src/content",
"schema": {
"path": "markdoc.config.mjs",
"type": "esm",
"property": "default",
"watch": true
}
}
]

markdoc.config.mjsschemaオブジェクトを持つ設定ファイルとして設定し、pathプロパティを使用してMarkdocファイルが保存されている場所を定義します。Markdocはコンテンツコレクションに固有であるため、src/contentを使用できます。

Markdocファイルは、コンテンツコレクション内でのみ使用できます。.mdoc拡張子を使用して、任意のコンテンツコレクションにエントリを追加します。

  • ディレクトリsrc/
    • ディレクトリcontent/
      • ディレクトリdocs/
        • why-markdoc.mdoc
        • quick-start.mdoc

次に、コンテンツコレクションAPIを使用してコレクションをクエリします。

src/pages/why-markdoc.astro
---
import { getEntry, render } from 'astro:content';
const entry = await getEntry('docs', 'why-markdoc');
const { Content } = await render(entry);
---
<!--dataでフロントマターのプロパティにアクセス-->
<h1>{entry.data.title}</h1>
<!--ContentコンポーネントでMarkdocのコンテンツをレンダリング-->
<Content />
Astroコンテンツコレクションのドキュメントで詳細を確認してください。

コンテンツに変数を渡す必要がある場合があります。これは、A/BテストなどのSSRパラメータを渡す場合に便利です。

変数は、Contentコンポーネントを介してプロップとして渡すことができます。

src/pages/why-markdoc.astro
---
import { getEntry, render } from 'astro:content';
const entry = await getEntry('docs', 'why-markdoc');
const { Content } = await render(entry);
---
<!--abTestパラメータをを渡す-->
<Content abTestGroup={Astro.params.abTestGroup} />

これで、abTestGroupdocs/why-markdoc.mdocで変数として利用できます。

src/content/docs/why-markdoc.mdoc
{% if $abTestGroup === 'image-optimization-lover' %}
画像の最適化についてお話ししましょう...
{% /if %}

すべてのMarkdocファイルにグローバルな変数を作成するには、markdoc.config.mjs|tsからvariables属性を使用できます。

markdoc.config.mjs
import { defineMarkdocConfig } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({
variables: {
environment: process.env.IS_PROD ? 'prod' : 'dev',
},
});

Markdocコンテンツからフロントマターにアクセスする

Section titled “Markdocコンテンツからフロントマターにアクセスする”

フロントマターにアクセスするには、コンテンツをレンダリングする場所でエントリのdataプロパティをを渡すことができます。

src/pages/why-markdoc.astro
---
import { getEntry, render } from 'astro:content';
const entry = await getEntry('docs', 'why-markdoc');
const { Content } = await render(entry);
---
<Content frontmatter={entry.data} />

これは、Markdocで$frontmatterとしてアクセスできるようになりました。

コンポーネントのレンダリング

Section titled “コンポーネントのレンダリング”

@astrojs/markdocは、Markdocのすべての機能を使用し、UIコンポーネントをコンテンツに接続するための設定オプションを提供します。

AstroコンポーネントをMarkdocタグとして使用する

Section titled “AstroコンポーネントをMarkdocタグとして使用する”

.astroコンポーネントにマッピングされるMarkdocタグを設定できます。プロジェクトのルートにmarkdoc.config.mjs|tsファイルを作成し、tag属性を設定することで、新しいタグを追加できます。

この例では、Asideコンポーネントをレンダリングし、typepropを文字列として渡すことができます。

markdoc.config.mjs
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({
tags: {
aside: {
render: component('./src/components/Aside.astro'),
attributes: {
// Markdocは各属性に型定義を要求します。
// これらは、レンダリングしているコンポーネントの
// `Props`型を反映する必要があります。
// 属性の定義に関するMarkdocのドキュメントを参照してください
// https://markdoc.dev/docs/attributes#defining-attributes
type: { type: String },
},
},
},
});

このコンポーネントは、{% aside %}タグを使用してMarkdocファイルで使用できるようになりました。子はコンポーネントのデフォルトスロットに渡されます。

# Markdocへようこそ👋
{% aside type="tip" %}
この派手な「aside」のようなタグを使用して、ドキュメントに_センス_を加えてください。
{% /aside %}

クライアントサイドUIコンポーネントを使用する

Section titled “クライアントサイドUIコンポーネントを使用する”

タグとノードは.astroファイルに制限されています。クライアントサイドUIコンポーネントをMarkdocに埋め込むには、フレームワークコンポーネントをレンダリングするラッパー.astroコンポーネントを使用し、目的のclient:ディレクティブを指定します。

この例では、React Aside.tsxコンポーネントをClientAside.astroコンポーネントでラップします。

src/components/ClientAside.astro
---
import Aside from './Aside';
---
<Aside {...Astro.props} client:load />

このAstroコンポーネントは、設定内の任意のタグまたはノードrenderpropに渡すことができるようになりました。

markdoc.config.mjs
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({
tags: {
aside: {
render: component('./src/components/ClientAside.astro'),
attributes: {
type: { type: String },
},
},
},
});

npmパッケージとTypeScriptファイルからAstroコンポーネントを使用する

Section titled “npmパッケージとTypeScriptファイルからAstroコンポーネントを使用する”

TypeScriptまたはJavaScriptファイルから名前付きエクスポートとして公開されているAstroコンポーネントを使用する必要がある場合があります。これは、npmパッケージやデザインシステムを使用する場合によくあります。

component()関数の2番目の引数としてインポート名を渡すことができます。

markdoc.config.mjs
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({
tags: {
tabs: {
render: component('@astrojs/starlight/components', 'Tabs'),
},
},
});

これにより、内部で次のインポートステートメントが生成されます。

import { Tabs } from '@astrojs/starlight/components';

{% partial /%}タグを使用すると、Markdocコンテンツ内に他の.mdocファイルをレンダリングできます。

これは、複数のドキュメントでコンテンツを再利用する場合に便利で、コレクションスキーマに従わない.mdocコンテンツファイルを持つことができます。

この例は、ブログコレクションエントリ内で使用するフッターのMarkdocパーシャルを示しています。

src/content/blog/_footer.mdoc
ソーシャルリンク:
- [Twitter / X](https://twitter.com/astrodotbuild)
- [Discord](https://astro.build/chat)
- [GitHub](https://github.com/withastro/astro)

{% partial /%}タグを使用して、ブログ投稿エントリの下部にフッターをレンダリングします。相対パスまたはインポートエイリアスを使用して、ファイルへのパスを指定してfile属性を適用します。

src/content/blog/post.mdoc
# 私のブログ投稿
{% partial file="./_footer.mdoc" /%}

@astrojs/markdocは、コードブロックをハイライトするためのShikiおよびPrism拡張機能を提供します。

extendsプロパティを使用して、Markdoc設定にshiki()拡張機能を適用します。オプションで、shiki設定オブジェクトを渡すことができます。

markdoc.config.mjs
import { defineMarkdocConfig } from '@astrojs/markdoc/config';
import shiki from '@astrojs/markdoc/shiki';
export default defineMarkdocConfig({
extends: [
shiki({
// Shikiの組み込みテーマから選択(または独自に追加)
// デフォルト: 'github-dark'
// https://shiki.style/themes
theme: 'dracula',
// 水平スクロールを防ぐためにワードラップを有効にする
// デフォルト: false
wrap: true,
// カスタム言語を渡す
// 注: Shikiには、`.astro`を含む無数の言語が組み込まれています!
// https://shiki.style/languages
langs: [],
}),
],
});

extendsプロパティを使用して、Markdoc設定にprism()拡張機能を適用します。

markdoc.config.mjs
import { defineMarkdocConfig } from '@astrojs/markdoc/config';
import prism from '@astrojs/markdoc/prism';
export default defineMarkdocConfig({
extends: [prism()],
});
Prismスタイルシートの設定については、構文ハイライトガイドを参照してください。

段落や太字のテキストなどの標準的なMarkdown要素をAstroコンポーネントとしてレンダリングしたい場合があります。このために、Markdocノードを設定できます。特定のノードが属性を受け取る場合、それらはコンポーネントのプロップとして利用できます。

この例では、カスタムのQuote.astroコンポーネントを使用してブロッククオートをレンダリングします。

markdoc.config.mjs
import { defineMarkdocConfig, nodes, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({
nodes: {
blockquote: {
...nodes.blockquote, // 他のオプションにはMarkdocのデフォルトを適用
render: component('./src/components/Quote.astro'),
},
},
});
すべての組み込みノードと属性については、Markdocノードのドキュメントを参照してください。

@astrojs/markdocは、見出しにアンカーリンクを自動的に追加し、コンテンツコレクションAPIを介してheadingsのリストを生成します。見出しのレンダリング方法をさらにカスタマイズするには、AstroコンポーネントをMarkdocノードとして適用できます。

この例では、renderプロパティを使用してHeading.astroコンポーネントをレンダリングします。

markdoc.config.mjs
import { defineMarkdocConfig, nodes, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({
nodes: {
heading: {
...nodes.heading, // デフォルトのアンカーリンク生成を維持
render: component('./src/components/Heading.astro'),
},
},
});

すべてのMarkdown見出しはHeading.astroコンポーネントをレンダリングし、次のattributesをコンポーネントのプロップとして渡します。

  • level: number 見出しレベル1〜6
  • id: string 見出しのテキストコンテンツから生成されたid。これは、コンテンツrender()関数によって生成されたslugに対応します。

たとえば、見出し### レベル3の見出し!は、コンポーネントのプロップとしてlevel: 3id: 'level-3-heading'を渡します。

Astroの<Image />コンポーネントは、Markdocで直接使用することはできません。ただし、ネイティブの![]()画像構文が使用されるたびにデフォルトの画像ノードを上書きするようにAstroコンポーネントを設定したり、追加の画像属性を指定できるカスタムMarkdocタグとして設定したりできます。

Markdocのデフォルト画像ノードを上書きする

Section titled “Markdocのデフォルト画像ノードを上書きする”

デフォルトの画像ノードを上書きするには、標準の<img>の代わりにレンダリングされるように.astroコンポーネントを設定できます。

  1. カスタムのMarkdocImage.astroコンポーネントをビルドして、画像から必要なsrcおよびaltプロパティを<Image />コンポーネントに渡します。

    src/components/MarkdocImage.astro
    ---
    import { Image } from "astro:assets";
    interface Props {
    src: ImageMetadata;
    alt: string;
    }
    const { src, alt } = Astro.props;
    ---
    <Image src={src} alt={alt} />
  2. <Image />コンポーネントには、![]()構文では提供できないリモート画像のwidthheightが必要です。リモート画像を使用する際のエラーを回避するには、リモートURLのsrcが見つかった場合に標準のHTML <img>タグをレンダリングするようにコンポーネントを更新します。

    src/components/MarkdocImage.astro
    ---
    import { Image } from "astro:assets";
    interface Props {
    src: ImageMetadata | string;
    alt: string;
    }
    const { src, alt } = Astro.props;
    ---
    <Image src={src} alt={alt} />
    {
    typeof src === 'string' ? <img src={src} alt={alt} /> : <Image src={src} alt={alt} />
    }
  3. Markdocを設定して、デフォルトの画像ノードを上書きし、MarkdocImage.astroをレンダリングします。

    markdoc.config.mjs
    import { defineMarkdocConfig, nodes, component } from '@astrojs/markdoc/config';
    export default defineMarkdocConfig({
    nodes: {
    image: {
    ...nodes.image, // 他のオプションにはMarkdocのデフォルトを適用
    render: component('./src/components/MarkdocImage.astro'),
    },
    },
    });
  4. .mdocファイル内のネイティブ画像構文は、<Image />コンポーネントを使用してローカル画像を最適化するようになります。リモート画像は引き続き使用できますが、Astroの<Image />コンポーネントではレンダリングされません。

    src/content/blog/post.mdoc
    <!-- <Image />によって最適化 -->
    ![猫の写真](/cat.jpg)
    <!-- 最適化されていない<img> -->
    ![犬の写真](https://example.com/dog.jpg)

カスタムMarkdoc画像タグを作成する

Section titled “カスタムMarkdoc画像タグを作成する”

Markdocのimageタグを使用すると、![]()構文では不可能な追加の属性を画像に設定できます。たとえば、カスタム画像タグを使用すると、widthheightが必要なリモート画像にAstroの<Image />コンポーネントを使用できます。

次の手順では、Astro <Image />コンポーネントを使用して画像を最適化し、キャプション付きの<figure>要素を表示するカスタムMarkdoc画像タグを作成します。

  1. 必要なpropsを受け取り、キャプション付きの画像をレンダリングするMarkdocFigure.astroコンポーネントを作成します。

    src/components/MarkdocFigure.astro
    ---
    // src/components/MarkdocFigure.astro
    import { Image } from "astro:assets";
    interface Props {
    src: ImageMetadata | string;
    alt: string;
    width: number;
    height: number;
    caption: string;
    }
    const { src, alt, width, height, caption } = Astro.props;
    ---
    <figure>
    <Image {src} {alt} {width} {height} />
    {caption && <figcaption>{caption}</figcaption>}
    </figure>
  2. Astroコンポーネントをレンダリングするようにカスタム画像タグを設定します。

    markdoc.config.mjs
    import { component, defineMarkdocConfig, nodes } from '@astrojs/markdoc/config';
    export default defineMarkdocConfig({
    tags: {
    image: {
    attributes: {
    width: {
    type: String,
    },
    height: {
    type: String,
    },
    caption: {
    type: String,
    },
    ...nodes.image.attributes
    },
    render: component('./src/components/MarkdocFigure.astro'),
    },
    },
    });
  3. Markdocファイルでimageタグを使用して、コンポーネントに必要なすべての属性を指定して、キャプション付きの図を表示します。

    {% image src="./astro-logo.png" alt="Astro Logo" width="100" height="100" caption="a caption!" /%}

markdoc.config.mjs|tsファイルは、タグ関数など、すべてのMarkdoc設定オプションを受け入れます。

これらのオプションは、markdoc.config.mjs|tsファイルのデフォルトエクスポートから渡すことができます。

markdoc.config.mjs
import { defineMarkdocConfig } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({
functions: {
getCountryEmoji: {
transform(parameters) {
const [country] = Object.values(parameters);
const countryToEmojiMap = {
japan: '🇯🇵',
spain: '🇪🇸',
france: '🇫🇷',
};
return countryToEmojiMap[country] ?? '🏳';
},
},
},
});

これで、任意のMarkdocコンテンツエントリからこの関数を呼び出すことができます。

¡Hola {% getCountryEmoji("spain") %}!
コンテンツでの変数や関数の使用方法の詳細については、Markdocのドキュメントを参照してください。

Markdocは、デフォルトでドキュメントを<article>タグでラップします。これは、document Markdocノードから変更できます。これは、ラッパー要素を削除したい場合は、HTML要素名またはnullを受け入れます。

markdoc.config.mjs
import { defineMarkdocConfig, nodes } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({
nodes: {
document: {
...nodes.document, // 他のオプションにはデフォルトを適用
render: null, // デフォルトは'article'
},
},
});

インテグレーション設定オプション

Section titled “インテグレーション設定オプション”

Astro Markdocインテグレーションは、markdoc.config.jsファイルでは利用できないMarkdocオプションと機能の設定を処理します。

Markdocタグやノードと並べてHTMLマークアップを記述できるようにします。

デフォルトでは、MarkdocはHTMLマークアップを意味のあるコンテンツとして認識しません。

HTML要素をコンテンツと並べて含めることができる、よりMarkdownらしいエクスペリエンスを実現するには、markdocインテグレーションオプションとしてallowHTML:trueを設定します。これにより、MarkdocマークアップでHTML解析が有効になります。

astro.config.mjs
import { defineConfig } from 'astro/config';
import markdoc from '@astrojs/markdoc';
export default defineConfig({
// ...
integrations: [markdoc({ allowHTML: true })],
});

デフォルトでは、4つのスペースでインデントされたコンテンツはコードブロックとして扱われます。残念ながら、この動作により、複雑な構造を持つドキュメントの読みやすさを向上させるために任意のレベルのインデントを使用することが困難になります。

Markdocでネストされたタグを使用する場合、タグ内のコンテンツをインデントして、深さのレベルが明確になるようにすると便利です。任意のインデントをサポートするには、インデントベースのコードブロックを無効にし、インデントベースのコードブロックを考慮する他のいくつかのmarkdown-it解析ルールを変更する必要があります。これらの変更は、ignoreIndentationオプションを有効にすることで適用できます。

astro.config.mjs
import { defineConfig } from 'astro/config';
import markdoc from '@astrojs/markdoc';
export default defineConfig({
// ...
integrations: [markdoc({ ignoreIndentation: true })],
});
# インデントされたタグを持つMarkdocへようこそ👋
# 注:インデントにはスペースまたはタブのいずれかを使用できます
{% custom-tag %}
{% custom-tag %} ### タグは読みやすくするためにインデントできます
{% another-custom-tag %}
ネストが多い場合にこれを追跡しやすくなります
{% /another-custom-tag %}
{% /custom-tag %}
{% /custom-tag %}

他のインテグレーション

UIフレームワーク

SSRアダプター

その他

貢献する コミュニティ スポンサー