日本語

開発者ツール · HTML WYSIWYG エディター

DOM からマークアップまで: innerHTML シリアル化が取得する HTML をどのように形成するか

· 仕組み

html htmlエンティティ 開発者ワークフロー

許可リスト リライターに入りバランス マークアップとして残される HTML トークン
オリジナル ToolAcre ベクトル イラスト

DOM ツリーを HTML 文字列に戻すときにブラウザーが従うルール (エスケープやエンティティから void 要素や属性の引用まで) と、エディターの出力がそのように見える理由について説明します。

このサニタイザーで <br> が <br /> として戻ってくる理由

`<br>` を含むソース フラグメントは、このサニタイザーを `<br />` のままにします。この結果は、すべてのブラウザが HTML をスラッシュでシリアル化していることを証明するものではありません。これは ToolAcre の文字列リライターにおける意図的な選択であり、その void 要素ブランチでは、許可されている br 要素と hr 要素に対してスペースとスラッシュが生成されます。

この区別により、よくある誤った説明が防止されます。ビジュアル サーフェスは innerHTML を通じて読み取られますが、コピーされたソースはアプリケーション コードによってトークン化され、再構築されます。ユーザーが受け取る内容には、ブラウザーで作成された DOM 文字列と、エイリアス、フィルター処理された属性、バランスのとれたタグなどの ToolAcre のより狭い出力規則の両方が反映されます。

トークン化、ホワイトリストの書き換え — これはブラウザーの innerHTML シリアル化ではありません

トークナイザーは、DOM ノードを構築したり DOMParser を呼び出したりせずに文字をスキャンします。テキスト、コメント、宣言、開始タグ、終了タグ、生のテキスト要素本体を認識します。サニタイズは、許可された構造を維持し、通常の未知のラッパーをアンラップし、危険なコンテナとその内容を抑制するというフラットなシーケンスを繰り返します。

したがって、元のスペルは保持されません。大文字と小文字が混在する名前は小文字になります。 bがstrong、iがem、strikeとdelがs、insがuになります。出力は、元の部分文字列として返されるのではなく、受け入れられたトークンから再生成されるため、ソースの書式設定やサポートされていない詳細は設計上消去されます。

既知のエンティティを正規化する際のテキストと属性のエスケープ

テキストは最初にエンティティ デコードされ、再度エスケープされます。アンパサンドは `&amp;` になり、小なり記号と大なり記号は `<` と `>` になり、禁止された制御文字は消えます。この順序により、既存の `&amp;` は `&amp;amp;` に変わるのではなく、繰り返されるパスにわたって安定した状態に保たれます。

属性値は、二重引用符、一重引用符、山かっこ、およびアンパサンドも引用する、より厳密なエスケープ パスに従います。既知のエンティティは、受け入れられた属性が出力される前にデコードされます。このテストでは、テキストおよびリンク クエリの冪等性を確認しますが、コードでは、名前付き参照と数値参照など、各著者エンティティのスペルの保持は保証されません。

カスタム リライターの無効な要素とバランスのとれた終了タグ

br と hr のみが両方とも許可され、出力セットでは void として分類されます。終了タグを受け取ることはありません。非 void 許可要素の場合、オープン スタックはネストを記録します。 Strong around em などの交差クローズにより、内部要素が最初にクローズされ、不正な順序が維持されるのではなく、バランスの取れたマークアップが生成されます。

閉じられていない要素は最後に閉じられますが、孤立した終了タグは無視されます。これはリライターのバランス調整ポリシーであり、ブラウザーの HTML5 エラー回復の完全な実装ではありません。ソース自体はパーサーの差分について警告しているため、出力を汎用の敵対的な入力サニタイザーとして販売してはなりません。

属性は許可リストに登録され、引用符で囲まれます。ソース注文だけでは契約ではありません

汎用属性バッグは存在しません。段落と見出しでは何も許可されません。リンクでは href と title を使用できます。略語を使用してタイトルを使用できます。引用は引用を許可します。順序付きリストでは開始と入力が可能です。出力されるすべての値は二重引用符で囲まれ、受け入れられたリンクも `rel="noopener noreferrer nofollow"` を取得します。

属性の順序は、受け入れられたトークンと追加された rel フィールドに従いますが、順序に依存すると脆弱になります。意味は、許可される名前と値にあります。不正な整数の開始は削除され、安全でない href スキームや cite スキームは拒否され、未知の属性は公開されたマークアップの一部になるのではなく、削除理由を生成します。

実用的な例: ToolAcre のサニタイザーを介したスニペットのラウンドトリップ

`<B class="loud">A &amp; B<br></B><a href="javascript:alert(1)">open</a>` をお試しください。クラスは削除され、B はstrong にマップされ、既存のアンパサンドは 1 つのエスケープされたアンパサンドのままになり、br は自動的に閉じられ、安全でないリンクは、表示されているリンク テキストを保持したまま href を失います。

プリティ ソース モードは、サポートされているブロック要素を行に配置し、リストの子をインデントします。インラインコンテンツは一緒に残し、pre 内のテキストを保持します。書式設定は、すでに書き換えられた出力を読みやすくするためのものです。これは 2 番目のセキュリティ パーサーではなく、以前の正規化によって削除された空白を復元しません。

これでカバーされないもの — ブラウザ、XML、または XHTML シリアル化

この記事では、ネイティブ ブラウザーのシリアル化保証、XMLSerializer、XHTML 構文、またはオプションの HTML 終了タグ ルール全般については説明しません。このリポジトリで観察可能な規則を文書化します。一般的なブラウザ シリアライザーではなく、ローカル エンティティ テーブルが認識される名前付き参照を決定するため、特に `&nbsp;` に関するクレームは省略されます。

プレビュー ビルダーはもう一度サニタイズし、フラグメントを完全な光をテーマにしたドキュメントにラップします。 HTML をコピーするとフラグメントが返されます。 HTML をダウンロードすると、そのドキュメントが返されます。これらは意図的に異なるアーティファクトです。ダウンロードされたファイルがコピーされたソースとバイト同一であると仮定する前に、アクション ラベルを読んでください。

要点: シリアライザーには一貫性がありますが、入力はそうではありませんでした — エディターの出力を予測する方法と、ToolAcre の HTML WYSIWYG エディターがブラウザーが実際に生成するものをどのように表示するかをまとめています。

ToolAcre は、文字列のトークン化、サポートされているエンティティのデコード、要素のエイリアスと許可リストの適用、URL の検査、受け入れられたタグのバランス、出力のエスケープ、およびオプションで出力の整形などの段階に従って予測します。このシーケンスは、innerHTML が単に作成者のソースを保存またはシリアル化していると言うよりも、実際の結果をより正確に説明しています。

ソース モードを使用して、長いドラフトを処理する前に小さなフィクスチャでリライトを観察します。サニタイザーは 500,000 文字を超えるドキュメントを拒否するため、サイズを超える入力はタブをフリーズするのではなく失敗します。宛先独自の HTML ポリシーを、このエディタの意図的にコンパクトなサブセットとは別にしてください。