From 8f764806d980ca964330d3151c93fd7229e21e17 Mon Sep 17 00:00:00 2001 From: 安竹洋平 <61961825+yasutakeyohei@users.noreply.github.com> Date: Wed, 31 Jan 2024 00:42:45 +0900 Subject: build --- build/blog/2024/01/26/new-flat-blog/index.html | 6 +++--- build/blog/2024/01/27/docusaurus-admonition-heading-toc/index.html | 7 ++++--- build/blog/archive/index.html | 6 +++--- build/blog/atom.xml | 5 +++-- build/blog/index.html | 6 +++--- build/blog/rss.xml | 5 +++-- build/blog/tags/docusaurus/index.html | 6 +++--- build/blog/tags/index.html | 6 +++--- build/blog/tags/v-3-1/index.html | 6 +++--- .../\343\201\212\347\237\245\343\202\211\343\201\233/index.html" | 6 +++--- "build/blog/tags/\346\212\200\350\241\223/index.html" | 6 +++--- 11 files changed, 34 insertions(+), 31 deletions(-) (limited to 'build/blog') diff --git a/build/blog/2024/01/26/new-flat-blog/index.html b/build/blog/2024/01/26/new-flat-blog/index.html index 6a5582c0..21c001e7 100644 --- a/build/blog/2024/01/26/new-flat-blog/index.html +++ b/build/blog/2024/01/26/new-flat-blog/index.html @@ -8,9 +8,9 @@ - - - + + +
メインコンテンツまでスキップ

新ふらっとブログ立ち上げました

· 約1分
安竹 洋平

今後の展開を考え、これまでの議会活動等のまとめをこの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の注意書きや警告文のタイトルを見出しにして、目次にも乗せる方法

· 約17分
安竹 洋平

Docusaurus🦖

@@ -64,6 +64,7 @@
markdownからHTMLへ変換処理の流れ
| ........................ 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形式
beforeDefaultRemarkPluginsremarkPlugins
Rehype
HTML形式
beforeDefaultRehypePluginsrehypePlugins
diff --git a/build/blog/archive/index.html b/build/blog/archive/index.html index d1702a67..c397644c 100644 --- a/build/blog/archive/index.html +++ b/build/blog/archive/index.html @@ -8,9 +8,9 @@ - - - + + + diff --git a/build/blog/atom.xml b/build/blog/atom.xml index 965fb731..4e835f80 100644 --- a/build/blog/atom.xml +++ b/build/blog/atom.xml @@ -64,6 +64,7 @@
markdownからHTMLへ変換処理の流れ
| ........................ 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形式
beforeDefaultRemarkPluginsremarkPlugins
Rehype
HTML形式
beforeDefaultRehypePluginsrehypePlugins
@@ -72,7 +73,7 @@

Swizzlingはこちらに説明がある通りの機能で、簡単に言うとReactのコンポーネントをカスタマイズできる機能です。

Swizzlingの設定をすると、Docusaurusがデフォルトのコンポーネントの代わりに自動的にカスタマイズしたコンポーネントを使用するようになります。

今回は、デフォルトのAdmonitionにないID属性を持たせるためAdmonitionコンポーネントをカスタマイズしました。Swizzlingの設定をすることにより、デフォルトのAdmonitionの代わりにこのカスタムコンポーネントが使われるようにします。

-

動作原理

+

動作原理

TOCは「ASTに含まれているheading要素を単純に配列に入れている」だけですが、この処理はカスタマイズで上書きできません。そこで、カスタマイズできる処理だけでAdmonitionのタイトルをTOCに反映する方法として次を思いつき、実装しました。

  1. docusaurusのデフォルトプラグインがTOCの処理を行うより前に、Admonitionのタイトル部を見出しとして新規作成し、Admonition要素の直前に追加する
  2. @@ -89,7 +90,7 @@

    Remark/Rehypeプラグイン

    次にプラグインを実装します。

    docusaurusのsrcディレクトリ下にrehypeとremarkというディレクトリを作り、次のファイル名と内容で2つのプラグインを作ります。

    -
    src/rehype/admonition-title-to-heading-before-toc.js
    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;
    +
    src/rehype/admonition-title-to-heading-before-toc.js
    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;
    src/rehype/admonition-title-to-heading-after-toc.js
    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;
    Admonitionのツリー構造

    参考までに、Remarkのプラグインから見るとAdmonitionのASTは例えば次のようになっています。

    Admonitionのツリー構造(一例)
    {
    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 @@ - - - + + +

    · 約17分
    安竹 洋平

    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 @@
    markdownからHTMLへ変換処理の流れ
    | ........................ 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形式
    beforeDefaultRemarkPluginsremarkPlugins
    Rehype
    HTML形式
    beforeDefaultRehypePluginsrehypePlugins
    @@ -73,7 +74,7 @@

    Swizzlingはこちらに説明がある通りの機能で、簡単に言うとReactのコンポーネントをカスタマイズできる機能です。

    Swizzlingの設定をすると、Docusaurusがデフォルトのコンポーネントの代わりに自動的にカスタマイズしたコンポーネントを使用するようになります。

    今回は、デフォルトのAdmonitionにないID属性を持たせるためAdmonitionコンポーネントをカスタマイズしました。Swizzlingの設定をすることにより、デフォルトのAdmonitionの代わりにこのカスタムコンポーネントが使われるようにします。

    -

    動作原理

    +

    動作原理

    TOCは「ASTに含まれているheading要素を単純に配列に入れている」だけですが、この処理はカスタマイズで上書きできません。そこで、カスタマイズできる処理だけでAdmonitionのタイトルをTOCに反映する方法として次を思いつき、実装しました。

    1. docusaurusのデフォルトプラグインがTOCの処理を行うより前に、Admonitionのタイトル部を見出しとして新規作成し、Admonition要素の直前に追加する
    2. @@ -90,7 +91,7 @@

      Remark/Rehypeプラグイン

      次にプラグインを実装します。

      docusaurusのsrcディレクトリ下にrehypeとremarkというディレクトリを作り、次のファイル名と内容で2つのプラグインを作ります。

      -
      src/rehype/admonition-title-to-heading-before-toc.js
      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;
      +
      src/rehype/admonition-title-to-heading-before-toc.js
      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;
      src/rehype/admonition-title-to-heading-after-toc.js
      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;
      Admonitionのツリー構造

      参考までに、Remarkのプラグインから見るとAdmonitionのASTは例えば次のようになっています。

      Admonitionのツリー構造(一例)
      {
      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件件あります

      全てのタグを見る

      · 約17分
      安竹 洋平

      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件件あります

      全てのタグを見る

      · 約17分
      安竹 洋平

      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件件あります

      全てのタグを見る

      · 約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 @@ - - - + + +