North Detail / ノースディテール

BLOG ブログ

ブログ
CATEGORY
TECH

VuePress プラグイン開発に挑戦 (ローカル編)

本記事は、 North Detail Advent Calendar 2019 の8日目の記事です。
Qiita にて作成した記事からの転記となります。 (2019年12月8日公開)

https://qiita.com/tacck/items/cb6d757a3cec1c1f9fe8

※本記事は、NorthDetail Advent Calendar 2019の一環として投稿しています

前置き

昨年に VuePress を知ってから、ちょっとしたドキュメントをまとめたサイトを作るのによく使っています。

Markdown でファイルをちゃちゃっと書けば、すぐに良い感じのサイトに仕立て上げられるので、すごく便利ですね。

ただ、コンテンツ全体を出すのにサイドバーにメニューを作っていかなきゃいけないんですが、それって結構面倒だなぁ、と思うんですよ。

「じゃぁ、プラグイン作っちゃえばよくね?」
と、思ったので挑戦してみました。

今回は NPM のパッケージではなく、ローカルに配置するパターンです。
また、作成した Markdown ファイルをアルファベット順に表示するだけ、です。
(これだけでも、シンプルなサイトなら十分楽になるので。)

準備

まず、 VuePress のプロジェクトを作りましょう。

$ mkdir sample-project
$ cd sample-project
$ yarn add -D vuepress
$ mkdir docs

できたら、順次下記ファイルを作成していきます。

ビルドなどを手軽にできるように、 package.json"scripts" 追加。

{
  "devDependencies": {
    "vuepress": "^1.2.0"
  },
  "scripts": {
    "docs:dev": "vuepress dev docs",
    "docs:build": "vuepress build docs"
  }
}

サンプル表示用に、いくつか Markdown ファイルを作成。

# 誰かの冒険

プラグイン作成のための冒険。

## 第1章: 旅立ち

[旅立ちます。](/01-departure)

## 第2章: 帰還

[ただいま。](/02-return)
# 第1章: 旅立ち

旅立ちます。

## 1.1: お城

王「ひのきの棒を与えよう。」
# 第2章: 帰還

ただいま。

## 2.1: お城

王「死んでしまうとは何ごとだ。」

この状態で、開発サーバを立ち上げて画面を確認します。

$ yarn docs:dev

http://localhost:8080/ をブラウザで表示してみましょう。

今の所サイドバーの設定はしていないので、何も表示されていませんね。

プラグイン作成へ

その前にサイドバーの設定をやる場合は

こんな感じで書きますね。

module.exports = {
  themeConfig: {
    sidebar: [
      '/',
      '/01-departure',
      '/02-return',
    ]
  }
}

こうやると、当然ブラウザでサイドバーにメニューが表示されますね。

表示確認できたら、 sidebar は不要なので消してください。

プラグインを読み込む設定

では、プラグインを作っていきましょう。
今回は、ローカルにあるプラグイン用の JavaScript を読み込みます。

Using a Plugin | VuePress

module.exports = {
  plugins: [
    require('./auto-sidebar')
  ]
}

docs/.vuepress/auto-sidebar のディレクトリの中に必要なファイルを作成していきます。

プラグインを書く

そもそも、サイドバーを変更するにはどうすれば良いのか。

実は情報をパッとは見つけられなくて、結構試行錯誤をしました。。。

その中で、 App Level EnhancementssiteData を操作すれば良さそうなことがわかったので、こちらを色々といじっていきます。

作成したページの情報は siteData.pages に入っており、これを使ってメニューに相当する配列を作成します。
作成した配列は siteData.themeConfig.sidebar に格納すればよさそうです。

では、実際にサイドバーにメニューを表示するプラグインを書いてみましょう。

色々な設定内容(API)があるので、詳しくはオフィシャルのドキュメントを確認してみてください。

Writing a Plugin | VuePress

今回はプラグイン内で App Level Enhancements を利用できるような設定を行ないます。
これは enhanceAppFiles というのを設定すれば良いです。

const path = require('path')

module.exports = (option, context) => ({
  enhanceAppFiles: path.resolve(__dirname, 'enhanceAppFile.js')
})

この設定で、実際の処理は同じディレクトリの enhanceAppFile.js でやるよ、というような意味になります。
では、実際の処理を見てみましょう。

export default ({ Vue, options, router, siteData }) => {
  const sidebar = []

  // regularPath を使うと、ページトップの `#` で宣言した内容をタイトルとして使ってくれる。
  for (const page of siteData.pages) {
    sidebar.push(page.regularPath)
  }

  // regularPath を昇順にソート
  sidebar.sort((page1, page2) => {
    return page1.localeCompare(page2)
  })

  siteData.themeConfig.sidebar = sidebar
}

確認

開発サーバ ( yarn docs:dev ) を起動していたら一旦終了して、再度立ち上げてください。
そして、再度 http://localhost:8080/ をブラウザで表示してみましょう。

設定を書いた時と同じように表示されましたね!

ここで、 Markdown 内のタイトルを変更したり、ファイルを追加したりすると、リアルタイムに変更・追加されることも確認できると思います。

例えば次のような Markdown を追加すると、

# 終章: そして伝説へ

お星さまになります。

すぐにブラウザに反映されます。

これで目的達成できました!

作成した分は、下記リポジトリに置いています。

https://github.com/tacck/vuepress-plugin-sidebar

今後

もう少し構成の凝ったサイトでも導入できるように、もうちょっと色々とやってみたいですね。

  • オプション対応
    • 固定のメニューを追加するなど
  • グルーピング対応
  • マルチ言語対応
  • NPM パッケージ化

徐々にチャレンジしていきます。

FAQ

Q. プラグインを修正しても反映されない?
A. ローカルサーバを起動しなおしてみよう。うまいやり方あったら教えて。

Q. どこに設定要素があるかわからん。
A. 自分もわからん。 console.log() で頑張ったので、うまいやり方あったら教えて。。

Q. 順番をもうちょっとコントロールしたい。
A. ファイル名で頑張る想定。ソートしている部分を好きにすれば好きにできるので、プラグインを拡張してね。

追記

固定メニューの追加対応して、 NPM パッケージとして公開しました。

vuepress-plugin-sidebar

tacck
WRITER:tacck
元 技術推進Group Group Leader

現在は株式会社ノースディテールを離れて、
エバンジェリストとして技術啓蒙や勉強会の開催、各種プロジェクトに参画しています。
機会があれば、ノースディテールでのプロジェクトに参加できればと思っています。

言語は問わずに対応しますが、心はPHPer。
フロントエンド・バックエンド・インフラ・スマホアプリなどを、
「垣根を超えて」どう作るか、を考えるのが好きです。

好きなフィギュアスケートの技はスプレッド・イーグル。
主な記事 一覧へ

一覧へ

IS 501383 / ISO 27001