Astro.js 小ネタ集 その2 Markdownの表示カスタマイズいろいろ
前回に引き続きAstro.jsでの小ネタを紹介していきます。
1. Markdown の"脚注"
MarkdownからHTML生成のメインのプラグイン?は remark-rehype
でやってます。
https://github.com/remarkjs/remark-rehype
"脚注"のカスタマイズは主にこのプラグインのオプションです。以下のようなオプションがあります。
- options.footnoteLabel
- options.footnoteLabelTagName
- options.footnoteLabelProperties
- options.footnoteBackLabel
それぞれの説明は上記のリンクを参照ください。 Astro.js でこのオプションを指定するには以下のようになります。
export default defineConfig({ ... markdown: { ... remarkRehype: { footnoteLabel: "脚注" }, ... } ... });
この例では"Footnote"の表記を"脚注"に変えてます。
デフォルトでタグがh2
になってるのもちょっと扱いずらいかもですね~。。。
2. Markdown の目次を表示
そもそもの"Markdownの目次"ですが、これはMarkdownの中で #
~ ########
などで指定した"見出し"のコレクションが目次になります。
見出しを抽出してリストにし、見た目を整えたものが目次となります。
Astro.js の CollectionEntry
は render()
メソッドの戻り値で見出しのリストが返ってきます。
... export async function getStaticPaths() { return (await getCollection('blog')).map(entry => ({ params: { id: entry.slug }, props: { entry }, })) } interface Props { entry: CollectionEntry<'blog'>; } const { entry } = Astro.props; const { Content } = await entry.render(); const { Content, headings } = await entry.render(); ...
このような感じで const { Content, headings } = await entry.render();
でheadings
に見出しのリストが返ってきます。
このクラスはMarkdownHeading
型で、これの定義は以下です。
export interface MarkdownHeading { depth: number; slug: string; text: string; }
depth
が見出しの深さでslug
がリンク用のアンカー、text
が見出しの文言です。
例えば以下のような感じでサクッと見出しを作成できます。
<article ...> <aside class="toc"> <ol class="toc-level-0"> {headings.filter(h => h.depth < 3).map((h,i) => { return ( <li class={`toc-level-${h.depth} toc-item`}><a href={`#${h.slug}`}>{h.text}</a></li> )})} </ol> </aside> <slot/> </article>
ここの例では .filter(h => h.depth < 3)
で深さが1,2だけの2段の見出しに絞っています。
あとは、スタイルシートで toc-level-1
toc-level-2
toc-level-3
などやっていけばいろいろ凝った段組みも可能ですね。
別出しにせずに本文内に入れ込んで簡単に目次を表示したい場合はremarkのプラグイン remark-toc を使うのもありかと思います。
3. Markdown のコードブロックにタイトルをつける
Markdown のコードブロックでよくある、
```ts:ファイル名
みたいなファイル形式とファイル名を指定できるの、よくあるじゃないですか? あれは Remark ではできなくて、プラグインでタイトルタグを生成して、スタイルシートで見た目を修正してます。 自分のブログサイトで使ってるプラグインは以下です。
https://github.com/ipikuka/remark-flexible-code-titles
まずはコイツをインストールします。
$ npm install remark-flexible-code-titles
続いて Astro.js の設定ファイルでプラグインを有効にします。
import remarkCodeTitles from "remark-flexible-code-titles"; export default defineConfig({ ... markdown: { ... remarkPlugins: [remarkCodeTitles], ... } ... });
で、準備は完了です。 これで、
```ts:filename
というMarkdwon だと以下のようなHTMLを生成してくれるようになります。
<div class="remark-code-container"> <div class="remark-code-title">filename</div> <pre class="astro-code" tabindex="0"> <code> ...
このようにタイトル付きのコードタグ、みたいなブロックを生成してくれます。
で、これを上記であげたように、カスタムのタグを当てればOKです。
... <style is:global> @tailwind components; @layer components { .remark-code-title { @apply text-base pl-3 rounded-t-lg font-bold; } .remark-code-title+pre { @apply mt-0 rounded-t-none; } } </style>
のような感じで、このサイトのコードブロック部分は作成してます。 その他にも remark-code-title などがあります。 生成されるタグは異なると思いますが、だいたいこんな流れでOKでしょう。(?)
本日はここまでといたします。 引き続きよろしくお願いいたします。