概要
GitBucket用のプラグイン GitBucket Markdown Enhanced Pluginを開発しています。
GitBucket Markdown Enhanced Plugin は、GitBucket 標準のマークダウンレンダリングエンジンを置き換えるプラグインです。
目標は、Visual Studio Code の Markdown Preview Enhanced 向けの markdown ファイルを軽易に Web で共有できる環境です。
これまで [TOC] という記法で生成した目次は、本文内に配置されていましたが、右側に独立させて固定配置するように修正し、バージョン 0.6.2 としてリリースしました。
issues や Pull Requests で使用した場合は、これまでどおり、本文に配置されます。
(必要ないですよね?)
また、複数箇所に [TOC] を記述した場合は、最初の目次のみ、右側に配置します。
前回の記事
Before After
これまで [TOC] という記法で生成した目次は、次の画像のように本文内に配置されていました。
今後は、次の画像のように本文の右側に固定配置されるようになります。
なお、ファイルリストが表示されている時など邪魔にならないようスクロール時に縦位置を調整するようにしています。
↓
また、右上の Table of Contents というタイトルをクリックすると目次を折りたためます。
以下、ソースの修正について、解説します。
TocExtension の設定を変更し目次にクラスを付与
flexmark-java の Table of Contents Extension(TocExtension) の LIST_CLASS オプションを設定し、目次が格納される <ul> タグにクラスを付与しました。
src/main/scala/io/github/yasumichi/gme/MarkdownEnhancedRenderer.scala に以下の行を追加しています。
options.set(TocExtension.LIST_CLASS, "toc")
目次のスタイル変更を行う JavaScript 関数の追加
src/main/resources/gme/assets/gme.js に以下の関数を追加しました。
var updateTocStyle = function() {
const toc = document.querySelector('.toc');
if (toc) {
const parent = toc.parentElement;
const details = document.createElement('details');
const summary = document.createElement('summary')
if (!document.location.toString().includes("/wiki/")) {
toc.style.height = `${document.documentElement.clientHeight * 0.7}px`
toc.style.overflowY = "scroll";
}
details.classList.add("toc-wrapper");
details.open = true;
summary.textContent = "Table of contents"
summary.classList.add("toc-summary");
parent.insertBefore(details, toc);
details.appendChild(summary);
details.appendChild(toc);
var parentY = parent.getClientRects()[0].y;
details.style.position = "fixed";
if (document.location.toString().includes("/wiki/")) {
details.style.right = "270px";
} else {
details.style.right = "20px";
}
if (parentY > 0) {
details.style.top = `${Math.floor(parentY)+2}px`;
} else {
details.style.top = "0px";
}
document.addEventListener("scrollend", (event) => {
var parentY = parent.getClientRects()[0].y;
if (parentY > 0) {
details.style.top = `${Math.floor(parentY)+2}px`;
} else {
details.style.top = "0px";
}
});
}
}
順番に説明していきます。
const toc = document.querySelector('.toc');
if (toc) {
// 中略
}
class 属性が、toc に設定されているノードを取得します。
取得できた場合、if ブロック内を実行します。
const parent = toc.parentElement;
const details = document.createElement('details');
const summary = document.createElement('summary')
if (!document.location.toString().includes("/wiki/")) {
toc.style.height = `${document.documentElement.clientHeight * 0.7}px`
toc.style.overflowY = "scroll";
}
wiki でないことを確認し、以下の処理を行います。
- toc の高さを document.documentElement.clientHeight の 70% に指定します。
- 上記高さに入らない項目がある場合、スクロールして表示できるよう overflow-y を
scrollに設定
details.classList.add("toc-wrapper");
details.open = true;
summary.textContent = "Table of contents"
summary.classList.add("toc-summary");
parent.insertBefore(details, toc);
details.appendChild(summary);
details.appendChild(toc);
以下の処理をしています。
-
<details> タグの class 属性に
toc-wrapperを追加 - <details> タグの open 属性を true に設定(開いておく)
-
<summary> タグの textContent を
Table of contentsに設定 -
<summary> タグの class 属性に
toc-summaryを追加 - 目次の親要素 parent の目次の前に <details> を挿入
- <details> タグの子として <summary> タグを追加
- <details> タグの子として目次を追加
var parentY = parent.getClientRects()[0].y;
details.style.position = "fixed";
if (document.location.toString().includes("/wiki/")) {
details.style.right = "270px";
} else {
details.style.right = "20px";
}
if (parentY > 0) {
details.style.top = `${Math.floor(parentY)+2}px`;
} else {
details.style.top = "0px";
}
document.addEventListener("scrollend", (event) => {
var parentY = parent.getClientRects()[0].y;
if (parentY > 0) {
details.style.top = `${Math.floor(parentY)+2}px`;
} else {
details.style.top = "0px";
}
});
document の scrollend イベントで目次の元親要素の縦位置から、<details> タグの top を変更します。




