NotFoundError: Node.removeChild: このノードの子として削除対象のノードが存在しません

テーマコンポーネントを開発しました:

これは BBCode を SVG に置き換えます。エディタのプレビューでも動作します。

問題は、エディタで文字を入力した際に、場合によってはエラーが発生することです:

NotFoundError: Node.removeChild: The node to be removed is not a child of this node

いくつかの要素を削除したことが原因だと確信しています。何も削除しなければ、このエラーは発生しません。

編集: 削除を行った瞬間ではなく、削除後にエディタで最初の文字を入力した際に発生します。

要素の削除は許可されていないのでしょうか?

もし許可されている場合、なぜこのエラーが発生するのでしょうか?

少し曖昧な質問で申し訳ありません。必要であれば、さらに詳細を提供できます。

スタックトレースは以下で確認できます:

編集 2: 私が削除するのは要素だけではありません。テキストノードのみを削除することもあります。

このシンプルなテーマコンポーネントで再現できます:

<script type="text/discourse-plugin" version="0.8">

  api.decorateCooked($elem => {
    if ($elem.get(0).className == 'd-editor-preview') {
      const $paragraphs = $elem.children('p');
      $.each($paragraphs, (paragraphIndex, paragraph) => {
        paragraph.remove();
      });
    }
  });

</script>
  1. 新しいトピックを作成する
  2. 入力を開始する。入力した2文字目で開発者コンソールにエラーが表示されます。

コンポーザープレビューは、cooked コンテンツをレンダリングするために Ember を使用しています。そのエラーは Ember のレンダリングエンジンから発生しているようです。おそらく、DOM が他の什么东西によって変更されたことで混乱しているのでしょう。

この問題を回避するために、ノードを remove() せず、代わりに display:none; や同様の方法で非表示にすることをお勧めします。

ありがとうございます。その回避策については以前から考えていたのですが、これが実際にバグなのかどうか、ご確認いただけますと幸いです。

コンポーザーのプレビューは、Ember のレンダリングとカスタムの ‘decorateCooked’ 関数の珍しい組み合わせです。これはその実装の癖によるもののようです。現在、特に回避策がシンプルで使いやすいことから、その動作を変更する予定はありません。

@j.jaffeux WidgetGlue を使用した際、api.cleanupStream にこの cleanUp 関数を渡している点に気づきました。

ウィジェットをアタッチした後、コンポーザーに書き込もうとすると、OP で報告されているエラーが発生します。特に、WidgetGlue.appendTo() でターゲットとした元の div data-wrap は完全に消えてしまいます。

編集:解決しました。[wrap=dice]div を生存させたままにできるよう、ウィジェットが消費するための「犠牲的な」<div> ノードを作成しました。

  // elem: <div class="d-wrap" data-wrap="dice">

  //- const glue = new WidgetGlue("dice-result", register, attrs);
  elem.innerHTML = "";
  //- glue.appendTo(elem);
  const sacrificial = document.createElement("div");
  elem.appendChild(sacrificial);
  attachDiceWidget(sacrificial, attrs);