EleventyでWiki用のテンプレートを作る
Eleventyは静的サイトジェネレータのひとつであり,Node.jsから利用可能である.本WebサイトもEleventyを用いて構築している.
Eleventy以外の静的サイトジェネレータのHugoと比べて, MarkdownItのプラグインが利用できたり,数式に必要なMathJaxをクライアント側で実行しなくて済むようにできる (個人的な) 利点がある.
EleventyはEleventyNavigationというプラグインによってページの階層構造を記述できる.しかしながら,階層構造を変えるには各記事のFront Matterを編集する必要があることから,ページの構造を大きく変えるような変更には手間がかかるため,WikiのようなWebページを作る用途には不向きであった.
上記の問題を解決するため,Eleventyプロジェクト内の記事ファイルの配置からEleventy Navigation用のFront Matterを自動生成可能なテンプレートの作成方法を紹介する.
本稿で作成したコードを公開しているリポジトリとサンプルサイトのURLは以下の通り:
Hello, Eleventy World!
プロジェクトの作成
適当なディレクトリを作り npm init
を実行する.作成された package.json
は以下のようになる.
{
"name": "11ty-minimal-wiki",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
"description": ""
}
パッケージの追加
package.json
にdevDependencies
を追加し,npm install
を実行してパッケージをインストールする.
{
"name": "11ty-minimal-wiki",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "MIT",
- "description": ""
+ "description": "",
+ "devDependencies": {
+ "@11ty/eleventy": "^2.0.1",
+ "@11ty/eleventy-navigation": "^0.3.5",
+ "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0",
+ "markdown-it": "^13.0.1",
+ "markdown-it-mathjax3": "^4.3.2"
+ }
}
Eleventyの設定ファイルを追加
プロジェクトルートにeleventy.config.js
を作成し,Eleventyの設定を記述する.
const markdownIt = require("markdown-it");
const pluginNavigation = require("@11ty/eleventy-navigation");
module.exports = function(eleventyConfig) {
const md = markdownIt({
html: true,
breaks: false,
linkify: true,
typographer: true,
});
md.use(require('markdown-it-mathjax3'));
eleventyConfig.setLibrary("md", md);
eleventyConfig.addPlugin(pluginNavigation);
return {
dir: {
input: "src",
}
};
}
Eleventyによるサイトのビルド
プロジェクトルートにsrc
ディレクトリを作成し,src/index.njk
に以下のHTMLを記述する.
<h1>It works!</h1>
package.json
のscripts
にビルド用のコマンドを追加する.
"scripts": {
+ "build": "eleventy",
+ "dev": "eleventy --serve --watch",
"test": "echo \"Error: no test specified\" && exit 1"
},
npm run dev
でプロジェクトをビルドしつつサーバを起動する.サーバのURL (http://localhost:8080) にアクセスすると,「It works!」とだけ書かれたWebページが表示される.
ページのテンプレートを書く
サイト全体のテンプレートを追加
src/_includes
ディレクトリを作成し,src/_includes/base.njk
ファイルにサイト全体で使用するテンプレートを記述する.
<!DOCTYPE html>
<html lang="{{ metadata.language }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>
{{ title or metadata.title }}{% if title %} | {{ metadata.title }}{% endif %}
</title>
</head>
<body>
<div class="content">
{{ content | safe }}
</div>
</body>
</html>
記事ページのテンプレートを追加
src/_includes/article.njk
に記事のテンプレートを記述する.
---
layout: base.njk
---
<h1>{{ title }}</h1>
{{ content | safe }}
メタデータの追加
src/_data
ディレクトリを作成し,src/_data/metadata.json
にサイトのメタデータを記述する.
{
"title": "Minimal Wiki",
"language": "ja"
}
src/contents
ディレクトリを作成し,src/contents/index.md
を作る.ファイルの内容は空のままにする.
記事のFront Matterを計算する関数を書く
EleventyのComputed Data (https://www.11ty.dev/docs/data-computed/) の機能を利用し,contents
ディレクトリ以下に配置された記事のFront Matterを計算する.
contents
以下ではディレクトリ分けがカテゴリの分類を表しており,カテゴリのメタデータはディレクトリ直下のindex.md
に書くものとする.
src/contents/contents.11tydata.js
を作成し,eleventyNavigation
の内容を生成するコードを書く.
module.exports = {
layout: 'article.njk',
eleventyComputed: {
eleventyNavigation: {
title: (data) => data.title,
key: (data) => {
const filepath = data.page.filePathStem;
if (path.basename(filepath) == 'index') {
return path.dirname(data.page.filePathStem);
} else {
return data.page.filePathStem;
}
},
parent: (data) => {
const filepath = data.page.filePathStem;
if (path.basename(filepath) == 'index') {
const dirname = path.dirname(path.dirname(data.page.filePathStem));
return dirname == '/' ? undefined : dirname;
} else {
return path.dirname(data.page.filePathStem);
}
},
order: (data) => data.order,
}
}
}
記事を追加
src/contents
以下に適当なディレクトリと記事ファイルを作成する.
contents
| contents.11tydata.js
| index.md
|
+---intro
| index.md
| install-packages.md
| install.md
|
\---python
hello.md
index.md
numpy.md
各.md
ファイルは記事を記述するファイルである.例えば,contents/intro/install.md
の内容は以下のようになっている.ファイル内にはeleventyNavigation
の階層構造を表すkey
,parent
は一切記述していないが,これらはcontents.11tydata.js
によってディレクトリ名やファイル名から自動で計算される.
---
title: Pythonのインストール
order: 10
---
1. Pythonの公式サイト (https://www.python.org/) にアクセスする
1. 「Downloads」→「Download Python 3.x.x」をクリックする (xの部分はバージョン)
各ファイルの詳しい内容は以下のページを参照されたい:
https://github.com/eqs/11ty-minimal-wiki/tree/8a3144222f2903e45dfc015bc8236a86935d5a46/src/contents
目次を追加
最後にsrc/index.njk
に目次を表示するコードを書く.
---
layout: base.njk
---
<h1>Minimal Wiki</h1>
{% set contents = collections.all | eleventyNavigation %}
{% set content = contents[0] %}
{%- for chapter in content.children -%}
<h4>{{ chapter.title }}</h4>
{%- for section in chapter.children -%}
<div class="content-row">
<a href="{{ section.url | url }}">
{{ section.title }}
</a>
</div>
{%- endfor -%}
{%- endfor -%}
以上の手順により作成したページは以下のURLから確認できる.
https://11ty-minimal-wiki.netlify.app/
おわり