Honkitのプラグインの書き方を調べてまとめた。
Gitbookと呼ばれていたものが、OSSの開発をやめて、
プロプライエタリなサービスに移行したため、
forkしてメンテが続けられているのがHonkit。
基本的にOSS時代のGitbookと互換している。
npmでgitbook-plugin-*
かhonkit-plugin-*
かで見つかるパッケージを、npm instal
して、book.json
のplugins:[]
に足せばOK。
自分が欲しい機能として、パンくずリストをページトップに出すというのがあるが、見つからなかった。
Honkit公式に詳しい情報は書いてる。
自分がたどった手順を残しておく。
npm init
package.json
を真似るengines
とhonkit.properties
というのがHonkit用に必要なもの。{
"name": "honkit-plugin-mytest",
"version": "0.0.1",
"description": "This is my first HonKit plugin",
"engines": {
"honkit": ">1.x.x"
},
"honkit": {
"properties": {
"myConfigKey": {
"type": "string",
"default": "it's the default value",
"description": "It defines my awesome config!"
}
}
}
}
ここにかいたプロパティがbook.json
から設定できるプロパティになる。
{
"plugins": [
"mytest"
],
"pluginsConfig": {
"mytest": {
"myConfigKey": "conf"
}
}
}
index.js
)に以下を記載module.exports = {
// Map of hooks
hooks: {},
// Map of new blocks
blocks: {},
// Map of new filters
filters: {}
};
index.js
のhooks:{}
にHonkit公式 - Hooks記載の名前と呼び出す関数を追加module.exports = {
hooks: {
"page": function(page) {
page.content = page.content.replace("<b>", "<strong>")
.replace("</b>", "</strong>");
return page;
}
}
};
index.js
のblocks:{}
にHonkit公式 - Extend Blocks記載の名前と呼び出す関数を追加module.exports = {
blocks: {
tag1: {
process: function(block) {
return "Hello "+block.body+", How are you?";
}
}
}
};
index.js
のfilters:{}
にHonkit公式 - Extend filters記載の名前と呼び出す関数を追加module.exports = {
filters: {
hello: function(name) {
return 'Hello '+name;
}
}
};
md→htmlに変換する前後とか様々なタイミングに割り込んで処理する。
markdonw内に独自のタグを用意して、md→htmlに変換するタイミングで関数によって独自にhtmlを出してあげる。
{% tag1 "argument 1", "argument 2", name="Test" %}
This is the body of the block.
{% endtag1 %}
markdown内でフォーマット変換を提供するシンボルを提供する。
{{ "2022-10-10"|ISO8601 }} => 2022-10-10T00:00:00.000
今回の要件は、hookのpage
のタイミングで、出来上がったhtmlの先頭にパンくずリストを表すhtmlを追加すれば良さそう
/*
test code
let home = '🏠'
let sep = '/'
let path = ''
let subdir = ''
let success = false
path = 'README.md'
subdir = ''
const breadcrumbs = createBreadCrumbs(path, subdir, home, sep)
success = breadcrumbs === '<div><a href="/">🏠</a> /</div>'
path = 'test.md'
subdir = ''
const breadcrumbs = createBreadCrumbs(path, subdir, home, sep)
success = breadcrumbs === '<div><a href="/">🏠</a> /</div>'
path = 'test/README.md'
subdir = ''
const breadcrumbs = createBreadCrumbs(path, subdir, home, sep)
success = breadcrumbs === '<div><a href="/">🏠</a> / <a href="/test/">test</a> /</div>'
path = 'test/test.md'
subdir = ''
const breadcrumbs = createBreadCrumbs(path, subdir, home, sep)
success = breadcrumbs === '<div><a href="/">🏠</a> / <a href="/test/">test</a> /</div>'
path = 'README.md'
subdir = 'subdir'
const breadcrumbs = createBreadCrumbs(path, subdir, home, sep)
let success = breadcrumbs === '<div><a href="/subdir/">🏠</a> /</div>'
path = 'test.md'
subdir = 'subdir'
const breadcrumbs = createBreadCrumbs(path, subdir, home, sep)
success = breadcrumbs === '<div><a href="/subdir/">🏠</a> /</div>'
path = 'test/README.md'
subdir = 'subdir'
const breadcrumbs = createBreadCrumbs(path, subdir, home, sep)
success = breadcrumbs === '<div><a href="/subdir/">🏠</a> / <a href="/subdir/test/">test</a> /</div>'
path = 'test/test.md'
subdir = 'subdir'
const breadcrumbs = createBreadCrumbs(path, subdir, home, sep)
success = breadcrumbs === '<div><a href="/subdir/">🏠</a> / <a href="/subdir/test/">test</a> /</div>'
*/
/*
path: not starts with '/' and not ends with '/'
subdir: starts with '/' and ends with '/'
home: home icon character
sep: separator character
*/
const createBreadCrumbs = (path, subdir, home, sep) => {
let breadcrumbs = '<div>'
breadcrumbs += `<a href="${subdir}">${home}</a> ${sep}`
const dirs = path.split('/').slice(0, -1)
let url = subdir
for (const dir of dirs) {
url += subdir + dir + '/'
breadcrumbs += ` <a href="${url}">${dir}</a> ${sep}`
}
breadcrumbs += '</div>'
return breadcrumbs
}
const normalizePath = (path) => {
return path.replace(/[\/]+/g, '/').replace(/^\//, '').replace(/\/$/, '')
}
const normalizeSubdir = (subdir) => {
const midpath = subdir.replace(/[\/]+/g, '/').replace(/^\//, '').replace(/\/$/, '')
return midpath === '' ? '/' : '/' + midpath + '/'
}
module.exports = {
hooks: {
'page': function(page) {
const config = this.config.get('pluginsConfig.breadcrumbs', {})
const path = normalizePath(page.path)
const subdir = normalizeSubdir(config.subdir || '')
const home = config.home || '🏠'
const sep = config.sep || '/'
page.content = createBreadCrumbs(path, subdir, home, sep) + page.content;
return page;
}
},
};
プラグイン側のルートディレクトリでnpm link
。
Honkit側のルートディレクトリでnpm link <プラグインのパッケージ名>
とやると、更新のたびにnpm install
しなくて済む。
初めて知った 。
これ、npm link
したら、次のnpm link <プラグインのパッケージ名>
でリンクできるパッケージのリストに追加するって仕組みみたい。