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にしました。