VS Codeのスニペット機能を使って内部リンクを簡単に生成する
Table Of Contents
本ブログは、Gatsby.js を使っているが、基本的に記事はローカルで Markdown で書いている。
そのため、ブログ内の他の記事へのリンクを貼る際に、Markdown のリンク記法を使う必要があるが、リンク先の記事のタイトルを毎回調べて、リンクを貼るのは面倒という問題があった。
そこで、VS Code のスニペットを使って、簡単にリンクを貼れるようにしたので、その方法をメモする。
前提
ローカルに記事情報を Markdown として管理している場合をここでは想定している。Contentful などの CMS を使っている場合は、また勝手が変わってくるともうので注意されたい。
VS Code のスニペット
VS Code のスニペットは、次のように設定する。
{
"Internal Link": {
"prefix": "link",
"body": "[${1:link text}](${2:https://example.com})",
"description": "Internal Link"
}
}
詳しくは次の記事を参照。
要するに、上記のフォーマットで適切なスニペットを生成できれば、VS Code のスニペットを使って、簡単にリンクを貼ることができる。
スニペットの生成
各ブログの Markdown ファイルにフロントマターを参照して、スニペットを生成する。
スニペットをするために次のようなスクリプトを書いた。
const fs = require("fs");
const fm = require("front-matter");
/**
* 指定フォルダ内のファイルを再帰的にすべて取得する
*/
const listFiles = (dir) => fs.readdirSync(dir, { withFileTypes: true }).flatMap((dirent) => (dirent.isFile() ? [`${dir}/${dirent.name}`] : listFiles(`${dir}/${dirent.name}`)));
// ブログ記事が格納されているフォルダを指定し、すべてのファイルのパスを取得する
const blogPosts = [...listFiles("content/blog"), ...listFiles("content/hatena")];
// 指定したMarkdonwのフロントマターを取得する
const blogFrontMatter = blogPosts
.map((path) => {
const file = fs.readFileSync(path, "utf8");
const { attributes } = fm(file);
return attributes;
})
.filter((a) => a.title);
// フロントマターからスニペットを生成する
const postsSnippets = blogFrontMatter.reduce((prev, cur) => {
const { title, description, slug, date } = cur;
const d = new Date(date);
const formattedDate = `${d.getFullYear()}${(d.getMonth() + 1).toString().padStart(2, "0")}${d.getDate().toString().padStart(2, "0")}`;
prev[title] = {
scope: "markdown",
prefix: `@blog:${formattedDate}/${slug}`,
body: [`[${title} | 飽き性の頭の中](/entry/${slug})`],
description: description ?? "",
};
return prev;
}, {});
// タグとカテゴリのスニペットを生成する(※ optional)
const tagsSnippets = Array.from(new Set(blogFrontMatter.map((fm) => fm.tags).flat()))
.filter((t) => t)
.reduce((prev, cur) => {
prev[cur] = {
scope: "markdown",
prefix: `@tag:${cur}`,
body: [cur],
description: cur ?? "",
};
return prev;
}, {});
const categoriesSnippets = Array.from(new Set(blogFrontMatter.map((fm) => fm.category)))
.filter((c) => c)
.reduce((prev, cur) => {
prev[cur] = {
scope: "markdown",
prefix: `@category:${cur}`,
body: [cur],
description: cur ?? "",
};
return prev;
}, {});
fs.writeFileSync(".vscode/blog-posts.code-snippets", JSON.stringify({ ...postsSnippets, ...tagsSnippets, ...categoriesSnippets }));
これを実行すると次のようなファイルが生成できる(見やすくするためにフォーマットしている)。
私の場合は、@
を最初につけることで、必要なときだけスニペットが呼び出されるようにしている。
この当たりは使い勝手に合わせて、カスタマイズしてもらえればと思う。
タグやカテゴリーを本ブログでは使っているので、それも合わせてスニペットにしている。表記ゆれやすでに何のタグやカテゴリーが使われているのかわからなくなるので、スニペットがあると適切なタグやカテゴリーが分かるので意外と助かる。
まとめ
あとは、必要なときにこのスクリプトを走らせれば、すぐにスニペットを最新に更新していける。
こうすることで、ブログ記事のリンクを貼るときに、手間を省けるようになった。