TOCはAstroで生成することにした

heroimage

やっぱり自動がいい

前回ObsidianでもTOCを生成できるようにしたと書いた。

ObsidianでもTOCしたい
ObsidianでもVScodeのようなTOCを実現する
ObsidianでもTOCしたい favicon http://ubanis.com/note/obsidian_toc
ObsidianでもTOCしたい

結局のところ手間がかかるのは一緒なのでAstroで自動生成するようにした。

以下が參考になりました。

[2023年6月版]Astro.js 小ネタ集 その2 Markdownの表示カスタマイズいろいろ
[2023年6月版]Astro.js 小ネタ集 その2 Markdownの表示カスタマイズいろいろ favicon https://zenn.dev/asopitech/articles/20230604-012854_1
[2023年6月版]Astro.js 小ネタ集 その2 Markdownの表示カスタマイズいろいろ

Contentの他にheadingsも読み込む

/src/pages/[...slug].astro
---
// ここでheadingsも読み込む
const { Content, headings } = await entry.render();
---
<!-- 中略 -->
<!-- BlogPostにheadingsを渡す -->
<BlogPost frontmatter={entry.data} headings={headings}>

BlogPost.astroでTOCを生成する

/src/layouts/BlogPost.astro
---
// 見出しが2つ以上の場合フラグを立てる
const headings_flag = headings.length > 2 ? true : false;
---
<!-- 中略 -->
<!-- フラグが立っていれば目次を作る -->
{
headings_flag && (
<aside class="toc">
<ul class="toc-level-0">
{headings
.filter((h) => h.depth < 6)
.map((h) => {
return (
<li class={`toc-level-${h.depth} toc-item`}>
<a href={`#${h.slug}`}>{h.text}</a>
</li>
);
})}
</ul>
</aside>
)
}
<!-- 見出しレベルに合わせたスタイル指定 -->
<style>
.toc-level-0 {
list-style: none;
}
.toc-level-3 {
margin-left: 2em;
}
.toc-level-4 {
margin-left: 4em;
}
.toc-level-5 {
margin-left: 6em;
}
#webmentions img {
max-height: 1.2em;
margin-right: -1ex;
}
</style>

最後に

ObsidianよりやっぱりVSCodeでMarkdown書いたほうが良い気がしてきた。
Syncthingが同期のときObsidianで編集中のファイルから無数にsync-conflictファイルを生み出したりするので。

iCloudの同期がおかしくなってしまったので同期は上記のとおりSyncthingにしました。