@astrojs/ markdoc
このAstroインテグレーションは、Markdocを使用してコンポーネント、ページ、およびコンテンツコレクションのエントリを作成できるようにします。
なぜMarkdocなのか
Section titled “なぜMarkdocなのか”Markdocを使用すると、AstroコンポーネントでMarkdownを強化できます。Markdocで作成された既存のコンテンツがある場合、このインテグレーションを使用すると、コンテンツコレクションを使用してそれらのファイルをAstroプロジェクトに持ち込むことができます。
インストール
Section titled “インストール”Astroには、公式インテグレーションのセットアップを自動化するためのastro add
コマンドが含まれています。もしよろしければ、手動でインテグレーションをインストールすることもできます。
新しいターミナルウィンドウで次のいずれかのコマンドを実行します。
npx astro add markdoc
pnpm astro add markdoc
yarn astro add markdoc
問題が発生した場合は、GitHubで報告してください。そして、以下の手動インストール手順を試してください。
手動インストール
Section titled “手動インストール”まず、@astrojs/markdoc
パッケージをインストールします。
npm install @astrojs/markdoc
pnpm add @astrojs/markdoc
yarn add @astrojs/markdoc
次に、integrations
プロパティを使用して、インテグレーションをastro.config.*
ファイルに適用します。
import { defineConfig } from 'astro/config';import markdoc from '@astrojs/markdoc';export default defineConfig({ // ... integrations: [markdoc()],});
VS Codeエディタの統合
Section titled “VS Codeエディタの統合”VS Codeを使用している場合は、構成されたタグの構文ハイライトとオートコンプリートを含む公式のMarkdoc言語拡張機能があります。詳細については、GitHubの言語サーバーを参照してください。
拡張機能をセットアップするには、プロジェクトのルートにmarkdoc.config.json
ファイルを作成し、次の内容を含めます。
[ { "id": "my-site", "path": "src/content", "schema": { "path": "markdoc.config.mjs", "type": "esm", "property": "default", "watch": true } }]
markdoc.config.mjs
をschema
オブジェクトを持つ設定ファイルとして設定し、path
プロパティを使用してMarkdocファイルが保存されている場所を定義します。Markdocはコンテンツコレクションに固有であるため、src/content
を使用できます。
Markdocファイルは、コンテンツコレクション内でのみ使用できます。.mdoc
拡張子を使用して、任意のコンテンツコレクションにエントリを追加します。
ディレクトリsrc/
ディレクトリcontent/
ディレクトリdocs/
- why-markdoc.mdoc
- quick-start.mdoc
次に、コンテンツコレクションAPIを使用してコレクションをクエリします。
---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 />
Markdoc変数を渡す
Section titled “Markdoc変数を渡す”コンテンツに変数を渡す必要がある場合があります。これは、A/BテストなどのSSRパラメータを渡す場合に便利です。
変数は、Content
コンポーネントを介してプロップとして渡すことができます。
---import { getEntry, render } from 'astro:content';
const entry = await getEntry('docs', 'why-markdoc');const { Content } = await render(entry);---
<!--abTestパラメータをを渡す--><Content abTestGroup={Astro.params.abTestGroup} />
これで、abTestGroup
はdocs/why-markdoc.mdoc
で変数として利用できます。
{% if $abTestGroup === 'image-optimization-lover' %}
画像の最適化についてお話ししましょう...
{% /if %}
すべてのMarkdocファイルにグローバルな変数を作成するには、markdoc.config.mjs|ts
からvariables
属性を使用できます。
import { defineMarkdocConfig } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ variables: { environment: process.env.IS_PROD ? 'prod' : 'dev', },});
Markdocコンテンツからフロントマターにアクセスする
Section titled “Markdocコンテンツからフロントマターにアクセスする”フロントマターにアクセスするには、コンテンツをレンダリングする場所でエントリのdata
プロパティをを渡すことができます。
---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
コンポーネントをレンダリングし、type
propを文字列として渡すことができます。
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
コンポーネントでラップします。
---import Aside from './Aside';---
<Aside {...Astro.props} client:load />
このAstroコンポーネントは、設定内の任意のタグまたはノードのrender
propに渡すことができるようになりました。
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番目の引数としてインポート名を渡すことができます。
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ tags: { tabs: { render: component('@astrojs/starlight/components', 'Tabs'), }, },});
これにより、内部で次のインポートステートメントが生成されます。
import { Tabs } from '@astrojs/starlight/components';
Markdocパーシャル
Section titled “Markdocパーシャル”{% partial /%}
タグを使用すると、Markdocコンテンツ内に他の.mdoc
ファイルをレンダリングできます。
これは、複数のドキュメントでコンテンツを再利用する場合に便利で、コレクションスキーマに従わない.mdoc
コンテンツファイルを持つことができます。
パーシャルファイルまたはディレクトリにはアンダースコア_
プレフィックスを使用します。これにより、パーシャルがコンテンツコレクションクエリから除外されます。
この例は、ブログコレクションエントリ内で使用するフッターのMarkdocパーシャルを示しています。
ソーシャルリンク:
- [Twitter / X](https://twitter.com/astrodotbuild)- [Discord](https://astro.build/chat)- [GitHub](https://github.com/withastro/astro)
{% partial /%}
タグを使用して、ブログ投稿エントリの下部にフッターをレンダリングします。相対パスまたはインポートエイリアスを使用して、ファイルへのパスを指定してfile
属性を適用します。
# 私のブログ投稿
{% partial file="./_footer.mdoc" /%}
構文のハイライト
Section titled “構文のハイライト”@astrojs/markdoc
は、コードブロックをハイライトするためのShikiおよびPrism拡張機能を提供します。
extends
プロパティを使用して、Markdoc設定にshiki()
拡張機能を適用します。オプションで、shiki設定オブジェクトを渡すことができます。
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()
拡張機能を適用します。
import { defineMarkdocConfig } from '@astrojs/markdoc/config';import prism from '@astrojs/markdoc/prism';
export default defineMarkdocConfig({ extends: [prism()],});
カスタムMarkdocノード/要素
Section titled “カスタムMarkdocノード/要素”段落や太字のテキストなどの標準的なMarkdown要素をAstroコンポーネントとしてレンダリングしたい場合があります。このために、Markdocノードを設定できます。特定のノードが属性を受け取る場合、それらはコンポーネントのプロップとして利用できます。
この例では、カスタムのQuote.astro
コンポーネントを使用してブロッククオートをレンダリングします。
import { defineMarkdocConfig, nodes, component } from '@astrojs/markdoc/config';
export default defineMarkdocConfig({ nodes: { blockquote: { ...nodes.blockquote, // 他のオプションにはMarkdocのデフォルトを適用 render: component('./src/components/Quote.astro'), }, },});
カスタム見出し
Section titled “カスタム見出し”@astrojs/markdoc
は、見出しにアンカーリンクを自動的に追加し、コンテンツコレクションAPIを介してheadings
のリストを生成します。見出しのレンダリング方法をさらにカスタマイズするには、AstroコンポーネントをMarkdocノードとして適用できます。
この例では、render
プロパティを使用してHeading.astro
コンポーネントをレンダリングします。
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〜6id: string
見出しのテキストコンテンツから生成されたid
。これは、コンテンツrender()
関数によって生成されたslug
に対応します。
たとえば、見出し### レベル3の見出し!
は、コンポーネントのプロップとしてlevel: 3
とid: 'level-3-heading'
を渡します。
カスタム画像コンポーネント
Section titled “カスタム画像コンポーネント”Astroの<Image />
コンポーネントは、Markdocで直接使用することはできません。ただし、ネイティブの![]()
画像構文が使用されるたびにデフォルトの画像ノードを上書きするようにAstroコンポーネントを設定したり、追加の画像属性を指定できるカスタムMarkdocタグとして設定したりできます。
Markdocのデフォルト画像ノードを上書きする
Section titled “Markdocのデフォルト画像ノードを上書きする”デフォルトの画像ノードを上書きするには、標準の<img>
の代わりにレンダリングされるように.astro
コンポーネントを設定できます。
-
カスタムの
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} /> -
<Image />
コンポーネントには、![]()
構文では提供できないリモート画像のwidth
とheight
が必要です。リモート画像を使用する際のエラーを回避するには、リモート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} />} -
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'),},},}); -
.mdoc
ファイル内のネイティブ画像構文は、<Image />
コンポーネントを使用してローカル画像を最適化するようになります。リモート画像は引き続き使用できますが、Astroの<Image />
コンポーネントではレンダリングされません。src/content/blog/post.mdoc <!-- <Image />によって最適化 --><!-- 最適化されていない<img> -->
カスタムMarkdoc画像タグを作成する
Section titled “カスタムMarkdoc画像タグを作成する”Markdocのimage
タグを使用すると、![]()
構文では不可能な追加の属性を画像に設定できます。たとえば、カスタム画像タグを使用すると、width
とheight
が必要なリモート画像にAstroの<Image />
コンポーネントを使用できます。
次の手順では、Astro <Image />
コンポーネントを使用して画像を最適化し、キャプション付きの<figure>
要素を表示するカスタムMarkdoc画像タグを作成します。
-
必要なpropsを受け取り、キャプション付きの画像をレンダリングする
MarkdocFigure.astro
コンポーネントを作成します。src/components/MarkdocFigure.astro ---// src/components/MarkdocFigure.astroimport { 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> -
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'),},},}); -
Markdocファイルで
image
タグを使用して、コンポーネントに必要なすべての属性を指定して、キャプション付きの図を表示します。{% image src="./astro-logo.png" alt="Astro Logo" width="100" height="100" caption="a caption!" /%}
高度なMarkdoc設定
Section titled “高度なMarkdoc設定”markdoc.config.mjs|ts
ファイルは、タグや関数など、すべてのMarkdoc設定オプションを受け入れます。
これらのオプションは、markdoc.config.mjs|ts
ファイルのデフォルトエクスポートから渡すことができます。
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") %}!
ルートHTML要素を設定する
Section titled “ルートHTML要素を設定する”Markdocは、デフォルトでドキュメントを<article>
タグでラップします。これは、document
Markdocノードから変更できます。これは、ラッパー要素を削除したい場合は、HTML要素名またはnull
を受け入れます。
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オプションと機能の設定を処理します。
allowHTML
Section titled “allowHTML”Markdocタグやノードと並べてHTMLマークアップを記述できるようにします。
デフォルトでは、MarkdocはHTMLマークアップを意味のあるコンテンツとして認識しません。
HTML要素をコンテンツと並べて含めることができる、よりMarkdownらしいエクスペリエンスを実現するには、markdoc
インテグレーションオプションとしてallowHTML:true
を設定します。これにより、MarkdocマークアップでHTML解析が有効になります。
import { defineConfig } from 'astro/config'; import markdoc from '@astrojs/markdoc';
export default defineConfig({ // ... integrations: [markdoc({ allowHTML: true })], });
allowHTML
が有効になっている場合、Markdocドキュメント内のHTMLマークアップは実際のHTML要素(<script>
を含む)としてレンダリングされるため、XSSなどの攻撃ベクトルが可能になります。HTMLマークアップが信頼できるソースからのものであることを確認してください。
ignoreIndentation
Section titled “ignoreIndentation”デフォルトでは、4つのスペースでインデントされたコンテンツはコードブロックとして扱われます。残念ながら、この動作により、複雑な構造を持つドキュメントの読みやすさを向上させるために任意のレベルのインデントを使用することが困難になります。
Markdocでネストされたタグを使用する場合、タグ内のコンテンツをインデントして、深さのレベルが明確になるようにすると便利です。任意のインデントをサポートするには、インデントベースのコードブロックを無効にし、インデントベースのコードブロックを考慮する他のいくつかのmarkdown-it解析ルールを変更する必要があります。これらの変更は、ignoreIndentationオプションを有効にすることで適用できます。
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 %}
- Astro Markdocスターターテンプレートは、AstroプロジェクトでMarkdocファイルを使用する方法を示しています。