Markdown→HTML変換後もハッシュを維持するremark-hash-heading

あけおめです。

このブログはMarkdown(正確にはMDX)で書いて、unifiedでHTMLへ変換しています。階層を分かりやすくするために、HTMLでもMarkdownみたいに見出し部分に##を付けてみました。

この「見出しのハッシュ##を維持する処理」をremarkプラグインremark-hash-headingとして公開したので紹介します。

## インストール

npmパッケージとして公開しているので、お好きなパッケージマネージャーでインストールしてください。

Terminal window
npm install remark-hash-heading

## 使い方

普通にコードで使うならこんな感じ。

import { remark } from "remark";
import remarkHtml from "remark-html";
import remarkHashHeading from "remark-hash-heading";
const result = await remark()
.use(remarkHashHeading)
.use(remarkHtml)
.process("## Hello World");
console.log(String(result));
// <h2>## Hello World</h2>

### Astroの設定例

このブログで実際に使っているAstroでの設定例も書いておきます。remarkPluginsの配列にimportしたやつを突っ込んでください。

astro.config.mjs
import { defineConfig } from "astro/config";
import remarkHashHeading from "remark-hash-heading";
export default defineConfig({
markdown: {
remarkPlugins: [
remarkHashHeading,
// [remarkHashHeading, { minDepth: 2 }],
],
},
});

minDepthなどのオプションの詳細はREADMEを読んでください。

## tocbotとの組み合わせ

このブログでは目次表示にtocbotを使ってます。目次にはハッシュ##は含んでほしくないので取り除いてます。

import { useEffect } from "react";
import tocbot from "tocbot";
const TOC = () => {
useEffect(() => {
tocbot.init({
// ...
headingLabelCallback: (label) => label.replace(/^#+ /, ""),
});
return () => tocbot.destroy();
}, []);
};

## リンク集


以上、自作のremarkプラグインremark-hash-headingの紹介でした。パッと見で階層の違いが分かるようになったので満足です。

unified系は、やりたいことをプラグインという形でサクッと差し込めるので便利です。