インストール
モジュールをインストールします
npm install @wordpress/block-serialization-default-parser --save
このパッケージは、あなたのコードがES2015+環境で実行されることを前提としています。そのような言語機能やAPIのサポートが限られているか、まったくない環境を使用している場合は、コードに@wordpress/babel-preset-default
で提供されるポリフィルを含める必要があります。
API
パース
入力HTMLをブロックベースの構造に変換するパーサー関数です。
使用法
入力ポスト:
<!-- wp:columns {"columns":3} -->
<div class="wp-block-columns has-3-columns">
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:paragraph -->
<p>Left</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:column -->
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:paragraph -->
<p><strong>Middle</strong></p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:column -->
<!-- wp:column -->
<div class="wp-block-column"></div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->
パースコード:
import { parse } from '@wordpress/block-serialization-default-parser';
parse( post ) ===
[
{
blockName: 'core/columns',
attrs: {
columns: 3,
},
innerBlocks: [
{
blockName: 'core/column',
attrs: null,
innerBlocks: [
{
blockName: 'core/paragraph',
attrs: null,
innerBlocks: [],
innerHTML: '\n<p>Left</p>\n',
},
],
innerHTML: '\n<div class="wp-block-column"></div>\n',
},
{
blockName: 'core/column',
attrs: null,
innerBlocks: [
{
blockName: 'core/paragraph',
attrs: null,
innerBlocks: [],
innerHTML: '\n<p><strong>Middle</strong></p>\n',
},
],
innerHTML: '\n<div class="wp-block-column"></div>\n',
},
{
blockName: 'core/column',
attrs: null,
innerBlocks: [],
innerHTML: '\n<div class="wp-block-column"></div>\n',
},
],
innerHTML:
'\n<div class="wp-block-columns has-3-columns">\n\n\n\n</div>\n',
},
];
パラメータ
- doc
string
: パースするHTMLドキュメント。
戻り値
理論
このパーサーは仕様パーサーと何が違うのか?
これは再帰的下降パーサーで、入力ドキュメントを一度線形にスキャンします。直接再帰するのではなく、スタックオーバーフローを防ぐためにトランポリンメカニズムを利用します。パース中の状態を追跡するためにグローバルを使用することで、データのコピーと渡しを最小限に抑えます。各トークン(ブロックコメント区切り)の間で、パーサーを計測し、必要に応じて介入することができます。たとえば、ドキュメントのパースにかかる時間に厳しい制限を設けたり、ドキュメントの追加デバッグ診断を提供したりすることができます。
仕様パーサーはパース表現文法(PEG)によって定義されており、私たちがこのパーサーで明示的に答えなければならない多くの質問に対して自動的に答えます。この実装の目標は、PEGの特性に一致させることで、直接交換可能にし、唯一の変更がより良いランタイムパフォーマンスとメモリ使用量であることです。
どのように機能するのか?
すべてのシリアライズされたグーテンベルクドキュメントは、名目上はHTMLドキュメントであり、通常のHTMLに加えて、特別に設計されたHTMLコメント—ブロックコメント区切り—を含むことがあります。これらはドキュメント内でシリアライズされたブロックを分離し、隔離します。
このパーサーは、これらの区切りからトリガーされる遷移の周りに状態マシンを作成しようとします—文法の「トークン」です。私たちがそれを見つけるたびに、次のいずれかを行うべきです:
- 新しいブロックに入る;
- ブロックから出る。
これらのアクションは文脈によって異なる効果を持ちます。たとえば、ブロックから出るときは、出力ブロックリストに追加する必要があるか、またはブロックスタック内の親ブロックの次のinnerBlock
として追加する必要があります(オープンブロックを追跡する場所)。詳細は以下に文書化されています。
このパーサーの最大の課題は、ネストの深さの各レベルでinnerHTML
値を構築するために必要なインデックスの正しい会計を行うことです。私たちはシンプルなアプローチを取ります:
- 新しく開かれた各ブロックを空の
innerHTML
で開始します。 - 最初のブロックを
innerBlocks
リストにプッシュするたびに、親ブロックのコンテンツが始まる場所からこの内部ブロックが始まる場所までのコンテンツを追加します。 - 別のブロックを
innerBlocks
リストにプッシュするたびに、前の内部ブロックが終了する場所からこの内部ブロックが始まる場所までのコンテンツを追加します。 - オープンブロックを閉じるときは、最後の内部ブロックが終了する場所から閉じるブロック区切りが始まる場所までのコンテンツを追加します。
- 内部ブロックがない場合は、オープニングとクロージングのブロックコメント区切りの間の全コンテンツを
innerHTML
として取ります。
パフォーマンスはどうか?
このパーサーは、仕様から生成されたパーサーよりもはるかに高速に動作します。私たちはPEGよりもパースについて多くのことを知っているため、速度とメモリ使用量を改善するためのいくつかのトリックを利用できます:
- 私たちは、見る角度によっては1つまたは2つの異なるトークンしか持っておらず、それらはすべて正規表現を介して簡単に一致します。文字ごとにパースするのではなく、PCRE RegExpエンジンに大きな文書の部分をスキップさせてトークンを見つけることができます。
preg_match()
がoffset
パラメータを取るため、各ステップで入力テキストのコピーを渡すことなく入力をクロールできます。文字列内の位置を追跡し、代わりに数値を渡すことができます。- すべての文字列をコピーしないことで、多くのメモリアロケーションをスキップできます。
さらに、正規表現を使用したトークン化には追加の利点があります。PEGによって生成されたパーサーは、トークン化ルールに対する制御と引き換えに予測可能なパフォーマンス特性を提供します—それは、PEGの保証を破るような壊滅的なバックトラッキングを防ぐために、ルール内で正規表現パターンを定義することを許可しません。
しかし、ブロックコメント区切りの「トークン言語」が正規であり、簡単に正規表現パターンと一致できるため、ここでそれを行うことができ、魔法のようなことが起こります: PHPやJavaScriptから飛び出し、ホストシステム上のCまたはC++で書かれた高度に最適化されたRegExpエンジンに入ります。これにより、仮想マシンとそのオーバーヘッドを離れます。
このパッケージへの貢献
これはグーテンベルクプロジェクトの一部である個別のパッケージです。このプロジェクトはモノレポとして整理されています。特定の目的を持つ複数の自己完結型ソフトウェアパッケージで構成されています。このモノレポ内のパッケージはnpmに公開され、WordPressや他のソフトウェアプロジェクトで使用されています。
このパッケージやグーテンベルク全体への貢献について詳しく知りたい場合は、プロジェクトの主要な貢献者ガイドをお読みください。