テーマ移行の残骸をAIで洗い出す手順|ホワイトリスト方式で見落としを防ぐ
WordPressのテーマを乗り換えたあと、記事を開くと空のボックスが出ていたり、吹き出しが素のテキストで並んでいたりすることがあります。旧テーマが用意していた独自ブロックやショートコードが、本文のHTMLにそのまま残っているのが原因です。
結論から書きます。テーマ移行の残骸は、旧テーマの名前で探さず、「現テーマで表示できるものの一覧(ホワイトリスト)」と照らし合わせて、そこに無いものを全部あぶり出します。さらに同じ記事を、まったく別の実装の検証スクリプトでもう一度調べ、両方で検出ゼロになってはじめて移行完了とします。
この記事は、散らかったサイトをAIで作り変えるマニュアルの「大規模修正」の作業の1つです。カテゴリやパーマリンクの作り直しを始める前に、旧テーマの痕跡を本文から消しておきます。
この作業で決まること
この作業が終わると、次の2つが決まります。
- 旧テーマの独自ブロック・ショートコード・CSSクラスが、どの記事に・何件残っているか
- 新テーマに切り替えた状態で、本当に表示が崩れていない記事はどれか
残骸がゼロだと確認できるまでは、本文に手を入れる次の作業(統合・分割・リライト)は始めません。残骸が残ったまま本文を書き換えると、「もともと旧テーマが原因で崩れていた」のか「今回の書き換えで壊した」のかが区別できなくなります。
前提:この記事の前に必要なもの
- AIにサイトを操作させる準備(WordPress REST API)が済んでいること
- 旧テーマから新テーマへの切り替え自体は済ませてあること(切り替え前に戻せる状態でバックアップを取ってから行う)
- Claude Code など、スクリプトを書いて実行できるAI
AIに渡すもの
AIに渡すのは次の3つです。
- 現テーマで表示できるブロック・ショートコード・クラスのホワイトリスト:WordPressコアの標準ブロック、現テーマが提供するブロック、使っているプラグインのブロックを並べる
- 旧テーマ由来とわかっている痕跡の例:移行作業の中で見つけた独自ブロックの名前空間、ショートコードのタグ名、CSSクラスの接頭辞。わかっているものだけでよい
- 読み取り専用で動く接続情報:記事を取ってくるだけで書き戻さない
ポイントは、旧テーマの名前を網羅しようとしないことです。自分のサイトで走査スクリプトを書いたときは、「旧テーマ固有の名前を推測で当てに行かない=見落とし防止」と設計の意図をコードの冒頭に書き残しました。知っている名前だけを並べたリストは、知らない名前を必ず取りこぼします。「現テーマで表示できるもの以外は全部おかしい」と考えて、残りを全部出させるほうが、知らない名前も表に上がってきます。
手順
- 現テーマの表示できる要素を列挙する
WordPressコアの標準ブロック(paragraph、heading、list、image、columns など)に加えて、新テーマと使用プラグインが提供するブロック名を書き出します。
- 全公開記事の「原文」をAPIで取る
wp-json/wp/v2/posts を context=edit で呼び、content.raw を取得します。表示後のHTMLではなく、Gutenbergのブロックコメント(<!-- wp:... -->)が残った原文です。残骸はここでしか判別できません。
- 本文を3つの観点で機械的に走査する
- ブロックコメントから名前空間を抜き、ホワイトリストに無いものを数える
- ショートコードのタグを抜き、WordPressコアの標準タグ以外を数える
- 旧テーマの接頭辞が付いたCSSクラスを数える
- 記事IDごとに所見を集計し、Markdownのレポートに出す
「非コアのブロック」「非コアのショートコード」「レガシークラス」の3見出しで、要素名と出現記事数を並べます。
- 検証を別の実装でもう一度行う
手順3と同じ記事を、別の判定方法で走査します。片方はホワイトリスト方式(表示できるもの以外を全部出す)、もう片方はブラックリスト方式(既知の旧テーマ要素を狙い撃ちする)です。正規表現も関数も共有しません。両方で検出ゼロになったときだけ完了とします。
- 残骸が出た記事を、新テーマで実際にブラウザで開く
機械の判定で残骸が無くても、表示が崩れていれば止めます。機械の判定で残骸があっても、新テーマが黙って無視して表示に影響しない場合もあるので、記事を開いて確認します。
手順5は見落とされがちです。次の「実際に起きた失敗」の節で、別実装の検証を置くに至った設計上の判断を書きます。
完了条件
- ☐ 公開記事の総数と、残骸を含む記事の数が、レポートに書かれている
- ☐ ホワイトリスト方式の走査で、未知のブロック・未知のショートコード・レガシークラスがいずれもゼロになっている
- ☐ 独立したブラックリスト方式の走査でも、同じ結果になっている
- ☐ 残骸が検出された記事を、新テーマでブラウザで開いて表示を目視で確認している
- ☐ 走査スクリプトは読み取り専用で、本文を書き戻していない
実際に起きた失敗
検出と検証を同じ実装で回していたら、片方の見落としを拾えなかった
自分のサイトでテーマを乗り換えたときの検証スクリプトには、ファイルの冒頭に「ポストモーテムの教訓: 検出と検証は別の手法で実装する」という注記を書き残しました。検出用のスクリプトと検証用のスクリプトで、正規表現も関数も共有していません。検出側はブラックリスト(これを消す)、検証側はホワイトリスト(これ以外は全部おかしい)と、方式そのものを変えています。
同じ関数を2本のスクリプトで使い回すと、見落とすパターンも共通になります。片方で「残り0件」と出ても、同じ漏れ方で0件になっているだけで、残骸が消えた保証にはなりません。実装を分けて方式も変えると、片方の見落としをもう片方が拾います。コードの冒頭に教訓を注記として残しているのは、将来の自分が「ここは共通化できる」と手を動かしかけたときに止めるためです。
旧テーマの名前を網羅しようとして、方式そのものを間違えた
もう1つの設計上の判断は、ブラックリスト方式を主役にしないことです。走査スクリプトのdocstringには、「推測で旧テーマの固有名を当てに行かない=見落とし防止」と書いています。旧テーマの独自ブロックの名前は、バージョンによって変わっていたり、プラグインが差し込んだクラスが混ざっていたりします。自分が思い出せる名前を列挙するだけでは、知らない名前はいつまでも検出に上がってきません。
対策は、WordPressコアの標準ブロックの集合をコードに書き、「それ以外の名前空間を含むブロックは全部所見として出す」仕様にすることです。既知の旧テーマ要素はブラックリスト側で狙い撃ちで数え、未知のものはホワイトリスト側ですくい上げます。両方を独立に動かすので、どちらかに書き忘れた名前も、もう片方で表に出ます。
よくある質問
Q. 旧テーマを有効化したまま走査してはいけませんか?
A. 旧テーマが生きていると、本来は壊れているはずのブロックも見た目は正常に表示されるので、残骸の重大さが分かりません。新テーマに切り替えてから走査します。切り替え自体を元に戻せる状態(バックアップ)は、走査の前に用意しておきます。
Q. 走査スクリプトは本文を書き換えてよいですか?
A. この記事で扱う走査スクリプトは、読み取り専用で動かします。書き換えは別の作業で、少ない件数で試し、変更前の本文を退避し、1回に触る件数の上限を決めてから行います。走査と修正を同じスクリプトに混ぜると、「残っていた」のか「スクリプトが書き戻した」のかが分からなくなります。
Q. 残骸が1件だけ残った場合、放置してよいですか?
A. 1件でも、同じテーマ由来の残骸が別の記事にもある可能性があります。手順5の検証を別方式でもう一度走らせて、本当に1件だけかを確かめてから判断します。
関連記事
- まとめ: 散らかったサイトの診断:どこから手をつけるかを決める【まとめ】
- サイトに必要なのは大規模・中規模・小規模どの修正か
- AIにサイトを操作させる準備(WordPress REST API)
- 重複記事を1本に統合して301リダイレクトでまとめる
- 孤立URLとパーマリンクの衝突を解消する
次の作業
- 残骸の消し込みを少数の記事で試す(読み取り専用の走査から、書き戻しの作業に進む)
- 残骸ゼロを確認したうえで、重複記事の統合と301リダイレクトに進む