今後の展開を考え、これまでの議会活動等のまとめをこのDocusaurusの仕組みに移行しています。
diff --git a/build/blog/2024/01/27/docusaurus-admonition-heading-toc/index.html b/build/blog/2024/01/27/docusaurus-admonition-heading-toc/index.html index 15057122..a39ef305 100644 --- a/build/blog/2024/01/27/docusaurus-admonition-heading-toc/index.html +++ b/build/blog/2024/01/27/docusaurus-admonition-heading-toc/index.html @@ -8,9 +8,9 @@ - - - + + +Docusaurusの注意書きや警告文のタイトルを見出しにして、目次にも乗せる方法
Docusaurus🦖
@@ -64,6 +64,7 @@| ........................ process ........................... |
| .......... parse ... | ... run ... | ... stringify ..........|
+--------+ +----------+
Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output
+--------+ | +----------+
X
|
+--------------+
| Transformers |
+--------------+
上図(Unified Overviewより)にTransformersとあるところがRemark/Rehypeの動作するところ。
Remarkはmarkdown形式で、RehypeはHTML形式でASTを扱います。どちらも同じようにASTを操作できますが、データ構造が違うため、目的に応じて選択することになるのかなと思います。
+こちらのサイトなどが詳しいです。
Docusaurusにおけるプラグインの実行タイミング
Docusaurusでこれらのプラグインを利用するためにはdocusaurus.config.jsonに設定が必要です。このページによると次の4種類の設定値にてプラグインを登録できます。
デフォルトプラグイン適用前 | デフォルトプラグイン適用後 | |
---|---|---|
Remark Markdown形式 | beforeDefaultRemarkPlugins | remarkPlugins |
Rehype HTML形式 | beforeDefaultRehypePlugins | rehypePlugins |
| ........................ process ........................... |
| .......... parse ... | ... run ... | ... stringify ..........|
+--------+ +----------+
Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output
+--------+ | +----------+
X
|
+--------------+
| Transformers |
+--------------+
上図(Unified Overviewより)にTransformersとあるところがRemark/Rehypeの動作するところ。
Remarkはmarkdown形式で、RehypeはHTML形式でASTを扱います。どちらも同じようにASTを操作できますが、データ構造が違うため、目的に応じて選択することになるのかなと思います。
+こちらのサイトなどが詳しいです。
Docusaurusにおけるプラグインの実行タイミング
Docusaurusでこれらのプラグインを利用するためにはdocusaurus.config.jsonに設定が必要です。このページによると次の4種類の設定値にてプラグインを登録できます。
デフォルトプラグイン適用前 | デフォルトプラグイン適用後 | |
---|---|---|
Remark Markdown形式 | beforeDefaultRemarkPlugins | remarkPlugins |
Rehype HTML形式 | beforeDefaultRehypePlugins | rehypePlugins |
Swizzlingはこちらに説明がある通りの機能で、簡単に言うとReactのコンポーネントをカスタマイズできる機能です。
Swizzlingの設定をすると、Docusaurusがデフォルトのコンポーネントの代わりに自動的にカスタマイズしたコンポーネントを使用するようになります。
今回は、デフォルトのAdmonitionにないID属性を持たせるためAdmonitionコンポーネントをカスタマイズしました。Swizzlingの設定をすることにより、デフォルトのAdmonitionの代わりにこのカスタムコンポーネントが使われるようにします。
-動作原理
+動作原理
TOCは「ASTに含まれているheading要素を単純に配列に入れている」だけですが、この処理はカスタマイズで上書きできません。そこで、カスタマイズできる処理だけでAdmonitionのタイトルをTOCに反映する方法として次を思いつき、実装しました。
- docusaurusのデフォルトプラグインがTOCの処理を行うより前に、Admonitionのタイトル部を見出しとして新規作成し、Admonition要素の直前に追加する @@ -89,7 +90,7 @@
- docusaurusのデフォルトプラグインがTOCの処理を行うより前に、Admonitionのタイトル部を見出しとして新規作成し、Admonition要素の直前に追加する @@ -90,7 +91,7 @@
Remark/Rehypeプラグイン
次にプラグインを実装します。
docusaurusのsrcディレクトリ下にrehypeとremarkというディレクトリを作り、次のファイル名と内容で2つのプラグインを作ります。
-import {visit} from 'unist-util-visit';
const plugin = (options) => {
const transformer = async (ast) => {
let newBeginningText = "";
const visitor = ((node, index, parent) => {
if (node.type === 'containerDirective') {
// :::infoなどに続くタイトル冒頭Text部(冒頭#を含む(もしくは含まない)部分)を取得(:::info ##** )
// (タイトル全体にはHTML等が含まれる可能性があるため冒頭Text部だけ操作する、残りはシャロ―コピー)
const beginningText = node.children[0].children[0].value;
// タイトル冒頭Text部に#が2つ以上連続しているとき
if(/^##/.test(beginningText)) {
// タイトル冒頭部から#とそれに続く空白を削除
newBeginningText = beginningText.replace(/^#+/, '').trim();
// タイトル部冒頭だけ更新し、残りはシャロ―コピー
// まずタイトル部全体をシャロ―コピー
let titleNodes = [...node.children[0].children];
// 冒頭要素のvalueを更新(ほかはシャロ―コピー)
const newTitleBeginningNode = {
...titleNodes[0],
value: newBeginningText,
}
// タイトルノードの冒頭要素だけ更新(ほかはシャロ―コピー)
const newTitleNodes = [ ...titleNodes ];
newTitleNodes[0] = newTitleBeginningNode;
// visitしているcontainerDirectiveの前にheadingノードを追加
parent.children.splice(index, 0, {
type: 'heading',
depth: (beginningText.match(/^##+/) || [''])[0].length, // #の連続数がheadingの深さ
children: newTitleNodes,
});
// 次に検索するのはindexを2つ分飛ばしたノード
return index + 2;
}
}
});
visit(ast, 'containerDirective', visitor);
};
return transformer;
};
export default plugin;
import {visit} from 'unist-util-visit';
const plugin = (options) => {
const transformer = async (ast) => {
let newBeginningText = "";
const visitor = ((node, index, parent) => {
if (node.type === 'containerDirective') {
// :::infoなどに続くタイトル冒頭Text部(冒頭#を含む(もしくは含まない)部分)を取得(:::info ##** )
// (タイトル全体にはHTML等が含まれる可能性があるため冒頭Text部だけ操作する、残りはシャロ―コピー)
const beginningText = node.children[0].children[0].value;
// タイトル冒頭Text部に#が2つ以上連続しているとき
if(/^##/.test(beginningText)) {
// タイトル冒頭部から#とそれに続く空白を削除
newBeginningText = beginningText.replace(/^#+/, '').trim();
// タイトル部冒頭だけ更新し、残りはシャロ―コピー
// まずタイトル部全体をシャロ―コピー
let titleNodes = [...node.children[0].children];
// 冒頭要素のvalueを更新(ほかはシャロ―コピー)
const newTitleBeginningNode = {
...titleNodes[0],
value: newBeginningText,
}
// タイトルノードの冒頭要素だけ更新(ほかはシャロ―コピー)
const newTitleNodes = [ ...titleNodes ];
newTitleNodes[0] = newTitleBeginningNode;
// visitしているcontainerDirectiveの前にheadingノードを追加
parent.children.splice(index, 0, {
type: 'heading',
depth: (beginningText.match(/^##+/) || [''])[0].length, // #の連続数がheadingの深さ
children: newTitleNodes,
});
// 次に検索するのはindexを2つ分飛ばしたノード
return index + 2;
}
}
});
visit(ast, 'containerDirective', visitor);
};
return transformer;
};
export default plugin;
import {visit} from 'unist-util-visit';
const plugin = (options) => {
const transformer = async (ast) => {
let hId = null;
let hContent = null;
visit(ast, 'element', (node, index, parent) => {
if (/^h[2-6]$/.test(node.tagName) && node.properties && node.properties.id) {
// H要素(h2~h6)を見つけた場合
// IDとタイトルの冒頭Text部を取得する
hId = node.properties.id;
hContent = node.children ? node.children[0].value :
node.children[0].children[0] ? node.children[0].children[0].value : '';
// 続くAdmonitionを探す(docはH要素とadmonitionが連続しているが
// blogではなぜか改行要素{ type:'text', value:'\n' }が間に入っているので念のため隣接3要素を探す
for (let i = index + 1; i < index + 4 && i < parent.children.length; i++) {
if(parent.children[i] && parent.children[i].tagName === 'admonition') {
// admonition(div)を見つけた場合
const admonitionNode = parent.children[i];
// admonitionタイトルの冒頭Text部分を取得(properties.titleもしくはchildren[0].children[0].value)
const admonitionNodeTitle = admonitionNode.properties.title ? admonitionNode.properties.title :
admonitionNode.children[0] && admonitionNode.children[0].children[0] ? admonitionNode.children[0].children[0].value : '';
if(/^##/.test(admonitionNodeTitle) && admonitionNodeTitle.replace(/^#+/, '').trim() === hContent.trim()) {
// #で始まっていて、タイトル冒頭部が同じ場合
// divのidをHタグのidに設定
admonitionNode.properties.id = hId;
// H要素を削除
parent.children.splice(index, 1);
}
}
}
}
});
};
return transformer;
};
export default plugin;
参考までに、Remarkのプラグインから見るとAdmonitionのASTは例えば次のようになっています。
{
type: 'containerDirective',
name: 'info',
attributes: {},
children: [
{
type: 'paragraph',
data: { directiveLabel: true },
children: [
{
type: 'text',
value: '#### info title もしHTML等が入ると(ここにaタグを入れると)',
position: [Object]
},
{
type: 'mdxJsxTextElement',
name: 'a',
attributes: [],
position: [Object],
data: [Object],
children: [Array]
},
{ type: 'text', value: 'このようにタイトル部が別々の要素として配列に入っている。', position: [Object] }
],
position: {
start: { line: 1347, column: 8, offset: 34053 },
end: { line: 1347, column: 55, offset: 34100 }
}
},
{ type: 'paragraph', children: [Array], position: [Object] },
...
],
...
}
Swizzling
diff --git a/build/blog/index.html b/build/blog/index.html index 09c19ce9..056fa2e1 100644 --- a/build/blog/index.html +++ b/build/blog/index.html @@ -8,9 +8,9 @@ - - - + + +Docusaurusの注意書きや警告文のタイトルを見出しにして、目次にも乗せる方法
Docusaurus🦖
diff --git a/build/blog/rss.xml b/build/blog/rss.xml index d128f782..6a58eac1 100644 --- a/build/blog/rss.xml +++ b/build/blog/rss.xml @@ -65,6 +65,7 @@| ........................ process ........................... |
| .......... parse ... | ... run ... | ... stringify ..........|
+--------+ +----------+
Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output
+--------+ | +----------+
X
|
+--------------+
| Transformers |
+--------------+
上図(Unified Overviewより)にTransformersとあるところがRemark/Rehypeの動作するところ。
Remarkはmarkdown形式で、RehypeはHTML形式でASTを扱います。どちらも同じようにASTを操作できますが、データ構造が違うため、目的に応じて選択することになるのかなと思います。
+こちらのサイトなどが詳しいです。
Docusaurusにおけるプラグインの実行タイミング
Docusaurusでこれらのプラグインを利用するためにはdocusaurus.config.jsonに設定が必要です。このページによると次の4種類の設定値にてプラグインを登録できます。
デフォルトプラグイン適用前 | デフォルトプラグイン適用後 | |
---|---|---|
Remark Markdown形式 | beforeDefaultRemarkPlugins | remarkPlugins |
Rehype HTML形式 | beforeDefaultRehypePlugins | rehypePlugins |
Swizzlingはこちらに説明がある通りの機能で、簡単に言うとReactのコンポーネントをカスタマイズできる機能です。
Swizzlingの設定をすると、Docusaurusがデフォルトのコンポーネントの代わりに自動的にカスタマイズしたコンポーネントを使用するようになります。
今回は、デフォルトのAdmonitionにないID属性を持たせるためAdmonitionコンポーネントをカスタマイズしました。Swizzlingの設定をすることにより、デフォルトのAdmonitionの代わりにこのカスタムコンポーネントが使われるようにします。
-動作原理
+動作原理
TOCは「ASTに含まれているheading要素を単純に配列に入れている」だけですが、この処理はカスタマイズで上書きできません。そこで、カスタマイズできる処理だけでAdmonitionのタイトルをTOCに反映する方法として次を思いつき、実装しました。
Remark/Rehypeプラグイン
次にプラグインを実装します。
docusaurusのsrcディレクトリ下にrehypeとremarkというディレクトリを作り、次のファイル名と内容で2つのプラグインを作ります。
-import {visit} from 'unist-util-visit';
const plugin = (options) => {
const transformer = async (ast) => {
let newBeginningText = "";
const visitor = ((node, index, parent) => {
if (node.type === 'containerDirective') {
// :::infoなどに続くタイトル冒頭Text部(冒頭#を含む(もしくは含まない)部分)を取得(:::info ##** )
// (タイトル全体にはHTML等が含まれる可能性があるため冒頭Text部だけ操作する、残りはシャロ―コピー)
const beginningText = node.children[0].children[0].value;
// タイトル冒頭Text部に#が2つ以上連続しているとき
if(/^##/.test(beginningText)) {
// タイトル冒頭部から#とそれに続く空白を削除
newBeginningText = beginningText.replace(/^#+/, '').trim();
// タイトル部冒頭だけ更新し、残りはシャロ―コピー
// まずタイトル部全体をシャロ―コピー
let titleNodes = [...node.children[0].children];
// 冒頭要素のvalueを更新(ほかはシャロ―コピー)
const newTitleBeginningNode = {
...titleNodes[0],
value: newBeginningText,
}
// タイトルノードの冒頭要素だけ更新(ほかはシャロ―コピー)
const newTitleNodes = [ ...titleNodes ];
newTitleNodes[0] = newTitleBeginningNode;
// visitしているcontainerDirectiveの前にheadingノードを追加
parent.children.splice(index, 0, {
type: 'heading',
depth: (beginningText.match(/^##+/) || [''])[0].length, // #の連続数がheadingの深さ
children: newTitleNodes,
});
// 次に検索するのはindexを2つ分飛ばしたノード
return index + 2;
}
}
});
visit(ast, 'containerDirective', visitor);
};
return transformer;
};
export default plugin;
import {visit} from 'unist-util-visit';
const plugin = (options) => {
const transformer = async (ast) => {
let newBeginningText = "";
const visitor = ((node, index, parent) => {
if (node.type === 'containerDirective') {
// :::infoなどに続くタイトル冒頭Text部(冒頭#を含む(もしくは含まない)部分)を取得(:::info ##** )
// (タイトル全体にはHTML等が含まれる可能性があるため冒頭Text部だけ操作する、残りはシャロ―コピー)
const beginningText = node.children[0].children[0].value;
// タイトル冒頭Text部に#が2つ以上連続しているとき
if(/^##/.test(beginningText)) {
// タイトル冒頭部から#とそれに続く空白を削除
newBeginningText = beginningText.replace(/^#+/, '').trim();
// タイトル部冒頭だけ更新し、残りはシャロ―コピー
// まずタイトル部全体をシャロ―コピー
let titleNodes = [...node.children[0].children];
// 冒頭要素のvalueを更新(ほかはシャロ―コピー)
const newTitleBeginningNode = {
...titleNodes[0],
value: newBeginningText,
}
// タイトルノードの冒頭要素だけ更新(ほかはシャロ―コピー)
const newTitleNodes = [ ...titleNodes ];
newTitleNodes[0] = newTitleBeginningNode;
// visitしているcontainerDirectiveの前にheadingノードを追加
parent.children.splice(index, 0, {
type: 'heading',
depth: (beginningText.match(/^##+/) || [''])[0].length, // #の連続数がheadingの深さ
children: newTitleNodes,
});
// 次に検索するのはindexを2つ分飛ばしたノード
return index + 2;
}
}
});
visit(ast, 'containerDirective', visitor);
};
return transformer;
};
export default plugin;
import {visit} from 'unist-util-visit';
const plugin = (options) => {
const transformer = async (ast) => {
let hId = null;
let hContent = null;
visit(ast, 'element', (node, index, parent) => {
if (/^h[2-6]$/.test(node.tagName) && node.properties && node.properties.id) {
// H要素(h2~h6)を見つけた場合
// IDとタイトルの冒頭Text部を取得する
hId = node.properties.id;
hContent = node.children ? node.children[0].value :
node.children[0].children[0] ? node.children[0].children[0].value : '';
// 続くAdmonitionを探す(docはH要素とadmonitionが連続しているが
// blogではなぜか改行要素{ type:'text', value:'\n' }が間に入っているので念のため隣接3要素を探す
for (let i = index + 1; i < index + 4 && i < parent.children.length; i++) {
if(parent.children[i] && parent.children[i].tagName === 'admonition') {
// admonition(div)を見つけた場合
const admonitionNode = parent.children[i];
// admonitionタイトルの冒頭Text部分を取得(properties.titleもしくはchildren[0].children[0].value)
const admonitionNodeTitle = admonitionNode.properties.title ? admonitionNode.properties.title :
admonitionNode.children[0] && admonitionNode.children[0].children[0] ? admonitionNode.children[0].children[0].value : '';
if(/^##/.test(admonitionNodeTitle) && admonitionNodeTitle.replace(/^#+/, '').trim() === hContent.trim()) {
// #で始まっていて、タイトル冒頭部が同じ場合
// divのidをHタグのidに設定
admonitionNode.properties.id = hId;
// H要素を削除
parent.children.splice(index, 1);
}
}
}
}
});
};
return transformer;
};
export default plugin;
参考までに、Remarkのプラグインから見るとAdmonitionのASTは例えば次のようになっています。
{
type: 'containerDirective',
name: 'info',
attributes: {},
children: [
{
type: 'paragraph',
data: { directiveLabel: true },
children: [
{
type: 'text',
value: '#### info title もしHTML等が入ると(ここにaタグを入れると)',
position: [Object]
},
{
type: 'mdxJsxTextElement',
name: 'a',
attributes: [],
position: [Object],
data: [Object],
children: [Array]
},
{ type: 'text', value: 'このようにタイトル部が別々の要素として配列に入っている。', position: [Object] }
],
position: {
start: { line: 1347, column: 8, offset: 34053 },
end: { line: 1347, column: 55, offset: 34100 }
}
},
{ type: 'paragraph', children: [Array], position: [Object] },
...
],
...
}
Swizzling
diff --git a/build/blog/tags/docusaurus/index.html b/build/blog/tags/docusaurus/index.html index 683943bf..66d14d9a 100644 --- a/build/blog/tags/docusaurus/index.html +++ b/build/blog/tags/docusaurus/index.html @@ -8,9 +8,9 @@ - - - + + +「docusaurus」タグの記事が2件件あります
全てのタグを見るDocusaurusの注意書きや警告文のタイトルを見出しにして、目次にも乗せる方法
Docusaurus🦖
diff --git a/build/blog/tags/index.html b/build/blog/tags/index.html index d4577ff0..770c1723 100644 --- a/build/blog/tags/index.html +++ b/build/blog/tags/index.html @@ -8,9 +8,9 @@ - - - + + + diff --git a/build/blog/tags/v-3-1/index.html b/build/blog/tags/v-3-1/index.html index ab7204e9..3348c9cb 100644 --- a/build/blog/tags/v-3-1/index.html +++ b/build/blog/tags/v-3-1/index.html @@ -8,9 +8,9 @@ - - - + + +「v3.1」タグの記事が1件件あります
全てのタグを見るDocusaurusの注意書きや警告文のタイトルを見出しにして、目次にも乗せる方法
Docusaurus🦖
diff --git "a/build/blog/tags/\343\201\212\347\237\245\343\202\211\343\201\233/index.html" "b/build/blog/tags/\343\201\212\347\237\245\343\202\211\343\201\233/index.html" index b4c97262..6ceb4f0e 100644 --- "a/build/blog/tags/\343\201\212\347\237\245\343\202\211\343\201\233/index.html" +++ "b/build/blog/tags/\343\201\212\347\237\245\343\202\211\343\201\233/index.html" @@ -8,9 +8,9 @@ - - - + + +「お知らせ」タグの記事が1件件あります
全てのタグを見る新ふらっとブログ立ち上げました
今後の展開を考え、これまでの議会活動等のまとめをこのDocusaurusの仕組みに移行しています。
diff --git "a/build/blog/tags/\346\212\200\350\241\223/index.html" "b/build/blog/tags/\346\212\200\350\241\223/index.html" index cd1f0ff5..71514f89 100644 --- "a/build/blog/tags/\346\212\200\350\241\223/index.html" +++ "b/build/blog/tags/\346\212\200\350\241\223/index.html" @@ -8,9 +8,9 @@ - - - + + +