【Astro】rehype (remark) プラグインを自作してMarkdown内の内部リンクをカードに変換する
AstroでMarkdown・MDXを扱う際、remark
及びrehype
のサードパーティプラグイン1のお世話になることが多いが、今回は自前で簡易的なrehypeプラグインを作ってみる。
やりたいこと
mdファイル内に埋め込んだ内部リンク (自サイトの別記事へのテキストリンク) をリンクカードに変換したい2。
[](/some-page)
上記のように/
から始まる相対パスの場合に内部リンクとみなす。
<a href="/some-page" class="internal-link"> <span>title</span> <time datetime="2000-01-01T00:00:00.000Z">2000-01-01</time></a>
<a>
には任意のクラスを指定し、タイトルと投稿日をリンク内に挿入する。
解決法
1. rehypeプラグインを実装
npm i unist-util-visit
hastをwalkするために、unist
のユーティリティモジュールunist-util-visitをインストールする。
import type { ElementContent, Root } from 'hast';import { visit } from 'unist-util-visit';
export default function rehypeInternalLink() { return (tree: Root) => { visit(tree, 'element', (node) => { if (node.tagName !== 'a') return; const href = node.properties.href; if (typeof href !== 'string' || !href.startsWith('/')) return;
const { title, createdAt } = getPost(href); // 何らかの方法で投稿情報を取得
const titleElm = { type: 'element', tagName: 'span', children: [ { type: 'text', value: title, }, ], } satisfies ElementContent; const timeElm = { type: 'element', tagName: 'time', properties: { dateTime: createdAt.toJSON() }, children: [ { type: 'text', value: formatDate(createdAt), }, ], } satisfies ElementContent;
node.children = [titleElm, timeElm]; node.properties.className = 'internal-link'; }); };}
hast (Node) をvisitし、<a>
かつhref
が相対パスであれば任意のElementを挿入する3。
import type { ElementContent, Root } from 'hast';import { visit } from 'unist-util-visit';import styles from './index.module.css';
export default function rehypeInternalLink() { return (tree: Root) => { visit(tree, 'element', (node) => { ...
node.children = [titleElm, timeElm]; node.properties.className = 'internal-link'; node.properties.className = styles.card; }); };}
もしCSS Modulesを利用している場合はclassName
に直接指定しスタイリングすることもできる。
2. 設定ファイルに追記
import rehypeInternalLink from './rehype-internal-link';
export default defineConfig({ markdown: { rehypePlugins: [rehypeInternalLink], },});
あとはAstroの設定ファイルのrehypePlugins
に指定すれば完成。リンクカードに変換されるようになった。
参考
-
remark/doc/plugins.md・rehype/doc/plugins.mdから一覧を参照できる ↩
-
外部リンクをリンクカードに変換する場合はremark-link-cardを利用するのが楽そう。OGP画像も表示してくれる ↩