PurifierFactory
in package
a-blog cms 向けに設定済みの HTMLPurifier インスタンスを組み立てる。
既存の設定・ブロックエディタ用属性に加えて、iframe / script のホスト whitelist を扱う:
- dangerous_tags に 'iframe' が無ければ HTML.SafeIframe を常時有効化し、許可ホストがあれば URI.SafeIframeRegexp をセット (whitelist が空でも src は全て無効化され、iframe を素通りさせない)。'iframe' を明示した場合のみタグごと削除する
- 提示・無害な属性(loading / referrerpolicy / allowfullscreen)は型付き AttrDef で宣言(CDATA 素通しを避ける)
- 権限付与系(allow / sandbox)は CDATA で宣言して編集者の入力を post-transform まで温存し、 IframePolicyTransform でホストポリシーの許可リストによりフィルタする
- dangerous_tags に 'script' が無ければ script を子要素なしの content model で宣言し(インライン JS を構造的に不可能にする)、 ScriptPolicyTransform で許可ホスト外の src を落とす。'script' を明示した場合のみタグごと削除する
- カスタム定義キャッシュのため HTML.DefinitionID を固定し、HTML.DefinitionRev を両ポリシーのハッシュから生成
拡張ポイントは引数のコールバック($configExtension / $definitionExtension)として受け取り、 フック発火(HookFactory 等のグローバル状態アクセス)は呼び出し側に閉じる。これにより本クラスは グローバル状態(config 定数・Hook)に依存せず、引数で受け取った値だけで構築するため単体テスト可能。
Table of Contents
Constants
- GROUP_BLOCK_TAGS = ['div', 'section', 'article', 'aside', 'header', 'footer', 'nav']
- グループブロック(ブロックエディター)が tag 属性で出力しうる要素。
- DEFINITION_ID = 'acms-html-purifier'
- カスタム HTML 定義を識別する固定 ID。HTML.DefinitionRev と組でキャッシュキーになる。
- GROUP_LANDMARK_TAGS = ['section', 'aside', 'nav']
- aria-label 入力欄(ハンドルメニューの「グループの設定」)を提供するランドマークタグ。
- REFERRER_POLICIES = ['no-referrer', 'no-referrer-when-downgrade', 'origin', 'origin-when-cross-origin', 'same-origin', 'strict-origin', 'strict-origin-when-cross-origin', 'unsafe-url']
- referrerpolicy で許可する標準値(Referrer-Policy 仕様の取りうる値)。
Methods
- create() : HTMLPurifier
- 設定済みの HTMLPurifier を生成する。
- addBlockEditorAttributes() : void
- ブロックエディター用の data 属性などを定義する(既存挙動を維持)。
- addGroupBlockAttributes() : void
- グループブロック(ブロックエディター)の属性を定義する。
- addIframeAttributes() : void
- iframe の許可属性を定義する。
- addScriptElement() : void
- 外部 script を許可ホスト限定で通すための script 要素を定義する。
- allowDataAttributes() : void
- すべての要素で `data-*` 属性を通す。
- definitionRevision() : int
- カスタム HTML 定義のリビジョン。iframe / script 双方のポリシーを合成し、 どちらを変更してもキャッシュが再生成されるようにする。
Constants
GROUP_BLOCK_TAGS
グループブロック(ブロックエディター)が tag 属性で出力しうる要素。
public
array<string|int, string>
GROUP_BLOCK_TAGS
= ['div', 'section', 'article', 'aside', 'header', 'footer', 'nav']
一次情報は packages/frontend/block-editor/src/extensions/Group/groupTags.ts の GROUP_ALLOWED_TAGS。 この配列を変更してもキャッシュキー(HTML.DefinitionRev)は自動では変わらない。 リリースを跨ぐ変更では Update/Engine が HTMLPurifier キャッシュを clearCache するため IframePolicy::CACHE_VERSION を上げる必要はないが、同一バージョン内の開発・QA 環境 (git デプロイでキャッシュディレクトリが引き継がれる環境)では古いキャッシュが残るため、 定義を変えたら cache ディレクトリの HTMLPurifier キャッシュを手動削除すること。
Why not main: HTML Standard は可視 main 要素を1文書1つに制限しており、編集者が グループブロックを使って複数の main を作れる経路を初版では意図的に閉じている (tag 選択肢自体は groupTags.ts 側の GROUP_ALLOWED_TAGS で管理、ここはそれに追従する)。 ただし data-* 属性は DataAttributeTransform で全要素一律に通すため、ここに main が無くても main に付いた data-type / data-tag は残る。複数 main を作らせない保証はエディター側 (groupTags.ts の safeGroupTagName が main を div にフォールバックする)が担う。
PHP 側の単一の情報源として、管理画面のグループタグ選択肢(ACMS_GET_Admin_BlockEditor_SettingsJson) もこの定数で絞り込む。
DEFINITION_ID
カスタム HTML 定義を識別する固定 ID。HTML.DefinitionRev と組でキャッシュキーになる。
private
mixed
DEFINITION_ID
= 'acms-html-purifier'
GROUP_LANDMARK_TAGS
aria-label 入力欄(ハンドルメニューの「グループの設定」)を提供するランドマークタグ。
private
mixed
GROUP_LANDMARK_TAGS
= ['section', 'aside', 'nav']
同一ページに複数の nav/aside/section があるとスクリーンリーダー利用者が区別できず、 section は accessible name が無いと region ロールにすらならないため(Fable 5 レビュー)。 一次情報は packages/frontend/block-editor/src/extensions/Group/groupTags.ts の GROUP_LANDMARK_TAGS。
REFERRER_POLICIES
referrerpolicy で許可する標準値(Referrer-Policy 仕様の取りうる値)。
private
array<string|int, string>
REFERRER_POLICIES
= ['no-referrer', 'no-referrer-when-downgrade', 'origin', 'origin-when-cross-origin', 'same-origin', 'strict-origin', 'strict-origin-when-cross-origin', 'unsafe-url']
Methods
create()
設定済みの HTMLPurifier を生成する。
public
static create(IframePolicy $iframePolicy, ScriptPolicy $scriptPolicy, array<string|int, string> $dangerousTags, string $cacheDir[, callable(HTMLPurifier_Config): void|null $configExtension = null ][, callable(HTMLPurifier_HTMLDefinition, HTMLPurifier_Config): void|null $definitionExtension = null ]) : HTMLPurifier
Parameters
- $iframePolicy : IframePolicy
-
iframe ホスト whitelist ポリシー
- $scriptPolicy : ScriptPolicy
-
script ホスト whitelist ポリシー
- $dangerousTags : array<string|int, string>
-
HTML.ForbiddenElements に渡す危険タグ(既定 ['form']。 'iframe' / 'script' を含めると whitelist を無視して常にタグごと削除するキルスイッチになる)
- $cacheDir : string
-
HTMLPurifier の Serializer キャッシュディレクトリ
- $configExtension : callable(HTMLPurifier_Config): void|null = null
-
カスタム HTML 定義の取得前に呼ばれる config 拡張フック。HTML.Allowed* / URI.* / CSS.* / Attr.* などの設定をここで上書き・追加できる(HTML.* は getDefinition 前に確定させる必要があるため)。
- $definitionExtension : callable(HTMLPurifier_HTMLDefinition, HTMLPurifier_Config): void|null = null
-
カスタム HTML 定義の取得後に呼ばれる定義拡張フック。addAttribute / addElement で要素・属性を 追加できる。定義を変更する場合は $configExtension 側で HTML.DefinitionRev を変更し、 キャッシュを再生成させること(変更がキャッシュに反映されないため)。
Return values
HTMLPurifieraddBlockEditorAttributes()
ブロックエディター用の data 属性などを定義する(既存挙動を維持)。
private
static addBlockEditorAttributes(HTMLPurifier_HTMLDefinition $def) : void
Parameters
- $def : HTMLPurifier_HTMLDefinition
addGroupBlockAttributes()
グループブロック(ブロックエディター)の属性を定義する。
private
static addGroupBlockAttributes(HTMLPurifier_HTMLDefinition $def) : void
グループブロックは tag 属性で出力要素を div / section / article などに切り替えるため、 div 以外のセクショニング要素にも data-type / data-tag を許可する必要がある。 許可する要素の一次情報は packages/frontend/block-editor/src/extensions/Group/groupTags.ts の GROUP_ALLOWED_TAGS。
Parameters
- $def : HTMLPurifier_HTMLDefinition
addIframeAttributes()
iframe の許可属性を定義する。
private
static addIframeAttributes(HTMLPurifier_HTMLDefinition $def, IframePolicy $policy) : void
(a) 提示・無害な属性は型付き AttrDef で宣言(CDATA 素通しを避ける)。width/height は HTML5 モジュールが Length で、title は Common で既に宣言済みのため追加しない。 (b) 権限付与系(allow / sandbox)は CDATA で宣言する。CDATA は値を検証しないため、 編集者が書いた生の値がそのまま post-transform(IframePolicyTransform)まで残り、 そこでホストポリシーの許可リストによりフィルタされた値に置き換わる。
Parameters
- $def : HTMLPurifier_HTMLDefinition
- $policy : IframePolicy
addScriptElement()
外部 script を許可ホスト限定で通すための script 要素を定義する。
private
static addScriptElement(HTMLPurifier_HTMLDefinition $def, ScriptPolicy $policy) : void
許可要素が空の ChildDef_Optional を与えることで、script は中身(=インライン JS)を 持てなくなる。HTMLPurifier は JS パーサを持たず中身の安全性を検証できないため、 判定軸を src の1点へ集約できるこの形を取る。src のホスト判定は ScriptPolicyTransform が担う。
Why not 'Optional:' の文字列指定にしないか: 同梱の Scripting モジュールが script に
ChildDef オブジェクトを設定しており、ElementDef::mergeIn は content_model が空文字の
指定を無視するため、文字列指定では元の ChildDef を置き換えられない。オブジェクトで
渡した場合のみ確実に上書きされる。
Why not content model を Empty にしないか: Empty にすると生成側が終了タグを出さない
(<script src="..."> で閉じない)ため、ブラウザの HTML パーサが以降の文書全体を
script の raw text として飲み込んでしまう。HTMLPurifier 同梱の SafeScripting モジュールが
同じ理由で Empty を避けており、それに倣う。
Why not HTMLPurifier 同梱の HTML.SafeScripting を使わないか: あちらは src の完全一致リストで、
iframe と同じ host[/pathPrefix] 形式(クエリ付き・パスがバージョンで変わる実際の埋め込み
スクリプト)を表現できない。設定の書式と解釈を iframe と揃えるために自前で宣言する。
Parameters
- $def : HTMLPurifier_HTMLDefinition
- $policy : ScriptPolicy
allowDataAttributes()
すべての要素で `data-*` 属性を通す。
private
static allowDataAttributes(HTMLPurifier_HTMLDefinition $def) : void
外部サービスの埋め込みスニペットは独自の data 属性に依存しており、宣言済みの属性しか通さない 既定の挙動では script のホストを許可しても埋め込みがレンダリングされない。詳細は DataAttributeTransform。
Parameters
- $def : HTMLPurifier_HTMLDefinition
definitionRevision()
カスタム HTML 定義のリビジョン。iframe / script 双方のポリシーを合成し、 どちらを変更してもキャッシュが再生成されるようにする。
private
static definitionRevision(IframePolicy $iframePolicy, ScriptPolicy $scriptPolicy) : int
Parameters
- $iframePolicy : IframePolicy
- $scriptPolicy : ScriptPolicy