AstroでMarkdownのレンダリングにカスタムコンポーネントを利用する
MDX のカスタムコンポーネント
Astro では、MDX 用にカスタムコンポーネントを利用できる機能が提供されている。
---import Heading from "../Heading.astro";---
<Content components={{ h1: Heading }} />
https://docs.astro.build/en/guides/markdown-content/#custom-components-with-imported-mdx
Markdown 用には同様の機能がない
利用方法がほとんど同じだが、マークダウンには同様の機能がない。拡張子を mdx に変更すれば、そのまま利用することは出来るが、それが望ましいとは限らない。
https://github.com/withastro/roadmap/discussions/769
https://github.com/withastro/roadmap/discussions/423
公式ドキュメントには MDX では出来るとは書かれているが、Markdown では出来ないとは書かれていないため、誤認したと思われる人による報告が見られる。
Remark plugin を利用する
Gatsby や Next.js などの他のフレームワークと同様に、remark plugin を利用して要素をカスタマイズすることは出来る。 一応 Astro 公式でも、カスタムコンポーネントを使う文脈ではないが remark plugin を利用する方法は紹介されている。
https://docs.astro.build/recipes/reading-time/
Astro のサンプルは、frontmatter を拡張するものだが、要素の変換も次のように行うことが出来る。
import { visit } from "unist-util-visit";import { toString } from "mdast-util-to-string";
const remarkPluginSample = () => { const transformer = (tree: any) => { visit(tree, (node) => { if (node.type !== "heading") return; let { depth } = node; if (depth !== 1) return;
let text = toString(node); const html = `<h1 style="color: coral">${text}</h1>`;
node.type = "html"; node.children = undefined; node.value = html; }); };
return transformer;};
export default defineConfig({ markdown: { remarkPlugins: [remarkPluginSample], },});
余談:公式 MDX Integration の拡張を考える
@astrojs/mdx
のコードをざっくり見ると、内部 API の addPageExtensionに.md
も追加すれば対応できるように思える。試してみて問題がなさそうであれば、PR を送ってみてもいいかもしれない。
個人的には Markdown の場合は既存のエコシステムを使うで十分だと思うので、今回は試さなかった。