飽き性の頭の中
VS Codeのスニペット機能を使って内部リンクを簡単に生成するのサムネイル

VS Codeのスニペット機能を使って内部リンクを簡単に生成する

2023-01-30に公開

ブログ運営
# VS Code# Gatsby.js# スニペット

本ブログは、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"
  }
}

詳しくは次の記事を参照。

VSCode の User Snippet を活用しよう! - Qiita

要するに、上記のフォーマットで適切なスニペットを生成できれば、VS Code のスニペットを使って、簡単にリンクを貼ることができる。

スニペットの生成

各ブログの Markdown ファイルにフロントマターを参照して、スニペットを生成する。

スニペットをするために次のようなスクリプトを書いた。

snippets.js
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 })
);

これを実行すると次のようなファイルが生成できる(見やすくするためにフォーマットしている)。

2023 01 30 14 24 49

私の場合は、@を最初につけることで、必要なときだけスニペットが呼び出されるようにしている。

この当たりは使い勝手に合わせて、カスタマイズしてもらえればと思う。

タグやカテゴリーを本ブログでは使っているので、それも合わせてスニペットにしている。表記ゆれやすでに何のタグやカテゴリーが使われているのかわからなくなるので、スニペットがあると適切なタグやカテゴリーが分かるので意外と助かる。

まとめ

あとは、必要なときにこのスクリプトを走らせれば、すぐにスニペットを最新に更新していける。

こうすることで、ブログ記事のリンクを貼るときに、手間を省けるようになった。

Profile picture

たわ / tawachan

1994年生まれ(29歳)

大学院修士課程(政治学)(2021-2023)

Web開発(2017-)

関連記事

タグ一覧

# 福岡:39# 東京:20# 大学院:13# 移住:10# エナジードリンク:9# Google:8# ブロックチェーン:8# Mac:7# Webエンジニア:7# Apple:6# Firebase:6# Sony:6# サントリー:6# Googleフォト:5# インドネシア:5# 埼玉:5# 英語:5# AWS:4# Canon:4# EOS 8000D:4# Kindle:4# Next.js:4# ZONe:4# ラーメン:4# 京都:4# 仮想通貨:4# 社会人:4# 鴨川シーワールド:4# Docker:3# EOS8000D:3# Lightroom:3# Markdown:3# Pixel:3# React Native:3# a7iii:3# d.school:3# iPad:3# iPad mini:3# アマルティア・セン:3# アメリカ:3# コワーキングスペース:3# セブンイレブン:3# デザイン思考:3# レッドブル:3# ワークショップ:3# 卒業旅行:3# 寿司:3# 紅葉:3# 長崎:3# API:2# ECR:2# ERC20:2# Expo.io:2# Firestore:2# Gatsby.js:2# GitHub Actions:2# Google Drive:2# Kindle Oasis:2# Kindle Paperwhite:2# LINE:2# MacBook Pro:2# NestJS:2# Notion:2# Oculus:2# Oculus Quest:2# Pixel Buds:2# React:2# TypeScript:2# Zotero:2# iPhone:2# pandoc:2# re:Invent:2# zsh:2# かき小屋:2# カフェ:2# ギグワーカー:2# サーチコンソール:2# ジャカルタ:2# スターバックス:2# ステーキ:2# スマートウォッチ:2# ソラマチ:2# チョコレート:2# ニューヨーク:2# バリ島:2# パンとエスプレッソと:2# ヒュッゲ:2# ビーチ:2# ブックスタンド:2# ブログ:2# マクドナルド:2# ミズマチ:2# モンスターエナジー:2# ワイヤレスイヤホン:2# 三千院:2# 両国:2# 修士論文:2# 兵庫:2# 千葉:2# 博多:2# 堀江貴文:2# 宮崎:2# 就活:2# 嵐山:2# 川越:2# 広島:2# 新宿御苑:2# 日米学生会議:2# 有馬温泉:2# 東寺:2# 東浩紀:2# 歴史:2# 民主主義:2# 江ノ島:2# 清澄白河:2# 独自ドメイン:2# 神奈川:2# 神戸:2# 転職:2

©2023 tawachan All Rights Reserved.