wp-discourseからの投稿で、マルチラインのHTMLコメントが非表示にならない

こんにちは

wp-discourse 固有の問題なのか、それとも Discourse 自体の HTML パーサーの問題なのかはわかりませんが、wp-discourse で生成された投稿では、複数行の HTML コメントが非表示になっていないようです。

Cory Doctorow さんの記事に基づいて、chinwag.pluralistic.net のセットアップを完了したばかりです。彼の投稿には、HTML コメントの形式で記事の上部にメタデータが含まれています。最近、この形式が単一行から複数行に変更されました。

以下の投稿でご確認いただけます:

元の記事の単一行コメントは削除されています:

一方、後続の投稿の複数行コメントはそのまま表示されています:

WordPress プラグインが原因ではないと思います。Discourse がコメントとして解釈されない例のマークアップを以下に示します。

<p><!--
Tags:


Summary:
New podcast; Europe's interop coalition; Scarfolk beermats; Miami cop owns illegal mansion nightclub; Video and transcript of my OII talk; Shower temperature vs handle position

URL:
https://pluralistic.net/2020/07/06/polbathic/

Title:
Pluralistic: 06 Jul 2020 polbathic

Bullet:
🧔🏿

Separator:
_,.-'~'-.,__,.-'~'-.,__,.-'~'-.,__,.-'~'-.,__,.-'~'-.,_

Top Sources:
Today's top sources: Fipi Lele, Naked Capitalism (https://www.nakedcapitalism.com/).

-->
<br>
</p>

レンダリング結果は以下の通りです。

問題は、コメント内の空行が Discourse によって段落として解釈されてしまうことです。その場合、HTML コメントは有効なマークアップではなくなります。コメント内の空行を削除すれば、Discourse によって正しく解釈されます。

<p><!--
Tags:
Summary:
New podcast; Europe's interop coalition; Scarfolk beermats; Miami cop owns illegal mansion nightclub; Video and transcript of my OII talk; Shower temperature vs handle position
URL:
https://pluralistic.net/2020/07/06/polbathic/
Title:
Pluralistic: 06 Jul 2020 polbathic
Bullet:
🧔🏿
Separator:
_,.-'~'-.,__,.-'~'-.,__,.-'~'-.,__,.-'~'-.,__,.-'~'-.,_
Top Sources:
Today's top sources: Fipi Lele, Naked Capitalism (https://www.nakedcapitalism.com/).
-->
<br>
</p>

投稿を Discourse に公開する前に投稿内容を編集する以外に、この問題に対処する最適な方法が何かはわかりません。

おそらく、Discourse に投稿を公開する前に投稿からコメントを削除するのが最善の方法でしょう。プラグインがデフォルトでこれを処理するべきかもしれませんが、この問題に遭遇したのは初めてです。

WP Discourse プラグインには、Discourse に公開される前に投稿内容を解析するためにフックできるフィルターが用意されています。そのフィルターの名前は wp_discourse_excerpt です。投稿内容は変数としてこのフィルターに渡されます。以下は、WordPress の投稿を Discourse に公開する前にすべてのコメントを削除するために、このフィルターを利用する方法です。このパターンを使えば、投稿を他の方法で変更することも可能です。

add_filter( 'wp_discourse_excerpt', 'wpdc_custom_discourse_excerpt' );
function wpdc_custom_discourse_excerpt( $html ) {
	if ( ! extension_loaded( 'libxml' ) ) {

		return $html;
	}

	$use_internal_errors   = libxml_use_internal_errors( true );
	$disable_entity_loader = libxml_disable_entity_loader( true );
	$html_doc              = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head><body>' . $html . '</body></html>';
	$doc                   = new \DOMDocument( '1.0', 'utf-8' );
	$doc->loadHTML( $html_doc );
	$finder   = new \DOMXPath( $doc );
	$comments = $finder->query( '//comment()' );
	if ( $comments->length ) {
		foreach ( $comments as $comment ) {
			$comment->parentNode->removeChild( $comment );
		}

		$parsed = $doc->saveHTML( $doc->documentElement );
		libxml_clear_errors();
		libxml_use_internal_errors( $use_internal_errors );
		libxml_disable_entity_loader( $disable_entity_loader );

		return preg_replace( '~<(?:!DOCTYPE|/?(?:html|head|meta|body))[^>]*>\s*~i', '', $parsed );
	}

	libxml_clear_errors();
	libxml_use_internal_errors( $use_internal_errors );
	libxml_disable_entity_loader( $disable_entity_loader );

	return $html;
}

このコードを WordPress テーマの functions.php ファイルに追加することで、問題が解決するはずです。もし動作しない場合は、WordPress サイトのサーバーで libxml 拡張機能が有効になっているか確認してください。

実際に試してみますが、コメント内の HTML エンティティが原因で Discourse がそのコメントを無効な HTML と判断してしまうのは、より大きな問題のように思えますが、どうでしょうか?

Discourse がこれをどのように扱うべきかについては確信が持てません。Discourse 上で直接作成された投稿については、サポートされる HTML のサブセットを限定すると考えるのは理にかなっていると思いますが、API を通じて作成された投稿や、RSS フィードから取り込まれた投稿については、Discourse がどの程度まで HTML をサポートすべきかは明確ではありません。

私が上記に投稿したコードを、WP Discourse プラグインに直接追加するのが妥当だと考えます。このプラグインはすでに、Discourse から WordPress に取り込まれたコメントを整理するために同様の機能を使用しています。これはすでに長期間使用されており、問題の報告は出ていません。これについては数日以内に改めてご連絡いたします。

これは WP Discourse バージョン 2.0.6 で追加されました。WordPress から Discourse に投稿の全文が公開される際、投稿内のコメントブロックは Discourse に送信される前に削除されます。

ありがとう、サイモン!利用でき次第インストールして、また報告します。

追伸:完璧に動きました。ありがとう!