1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[toc] を使ったら WordPress 投稿が『返答が正しい JSON レスポンスではありません』で保存できなくなった話

Posted at

― Table of Contents Plus × Gutenberg × REST API 地雷の正体と対処法

発生するエラーの状況

  • WordPressのブロックエディタ(Gutenberg)で投稿を保存しようとすると
  • 「更新に失敗しました。返答が正しい JSON レスポンスではありません」
  • Table of Contents Plus (TOC+)プラグインを使用している

再現条件と環境

  • WordPress 8.1.2
  • テーマ: オリジナルテーマ
  • Gutenbergエディタ使用
  • TOC+ バージョン: 2411.1
  • 仮ドメイン + 非SSL

エラーの技術的原因

  • GutenbergはREST APIで投稿を保存する
  • REST APIのrenderedフィールドにHTMLが含まれる
  • [toc]<!--TOC-->に置き換われ、the_content()フィルターでHTMLに変換される
  • そのHTMLの中に置き換符号の欠如やJSONと互換性のない文字列があるとJSON.parse()が爆死

やった対策一覧

プラグイン側

  • TOC+ の設定画面で「REST APIに直接含める」を OFFにする

テーマ側

  • rest_prepare_postフィルターでREST APIのrenderedだけTOC+を取り除いて再生成

5. 最終的な回避コード

add_filter( 'rest_prepare_post', function( \$response, \$post, \$request ) {
  remove_filter( 'the_content', [ \$GLOBALS['toc_plus'], 'the_content' ], 100 );
  \$response->data['content']['rendered'] = apply_filters( 'the_content', \$post->post_content );
  add_filter( 'the_content', [ \$GLOBALS['toc_plus'], 'the_content' ], 100 );
  return \$response;
}, 10, 3 );

これをfunctions.phpに追記することで、

  • 投稿本文に[toc]は残せる
  • 表示もそのまま
  • でもREST APIレスポンスだけTOCを削除でき、JSON.parse()エラーを防げる

補足: SSL環境での違い、Classic Editorとの関係

  • SSLでない場合:SameSite=LaxのCookieがRESTで送れず、未認証として返答が戻り、Gutenbergが爆死することがある
  • Classic EditorならRESTを通らず、そもそもこの問題が起こらない

まとめと教訓

  • 表示に問題がなくても、REST APIのrenderedが正式でないとJSONエラーは起きる
  • TOC+ の出力はちょっと前のタイミングでREST系には向いてない
  • 「入力は売る、出力はメンテする」の大事さを思い知らされた
  • いずれ直したのも、分析してコード書いたのも、しんどかったのも、結局ずっと現場にいた自分だった

使う側はわけもわからん。説明もない。でも実際には、たったこれだけで?ってなる1行のフィルターで、WordPress保存エラーは消える。
「保存失敗」を、少なくともこの現場からは消したい。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?