WordPressでコード表示を美しく行う「Highlighting Code Block(HCB)」と、記事販売サービス「Codoc(コードク)」を併用していると、以下のような問題が起こることがあります。
- Codoc経由で表示される記事で、コードブロックがハイライトされない
- コピー用のボタンが表示されない
この記事では、codocの表示領域に後から追加されるHCBブロックを再検査し、Prismのハイライトとコピー操作を補うコード例を紹介します。現在のcodocで必ず動作することを保証するものではありません。
codocの有料記事コンテンツ内でHighlighting Code Blockを表示する方法
既存のHCBコピーボタンがある場合は、その操作を維持します。ボタンがない場合だけ、別のクラス名の「コードをコピー」ボタンを追加し、ブラウザーのClipboard APIを使います。ClipboardJSの二重初期化は行いません。
以下のコードを、functions.phpに追記してください。
設置コード
add_action('wp_footer', function () {
if (!is_singular()) return;
?>
<script>
(() => {
const init = () => {
if (window.wazaCodocHcbReady) return;
window.wazaCodocHcbReady = true;
const highlighted = new WeakMap();
const controls = new WeakMap();
let pending = false;
const scan = () => {
pending = false;
document.querySelectorAll('.codoc-entries .hcb_wrap').forEach(wrap => {
const code = wrap.querySelector('pre code');
if (!code) return;
const text = code.textContent;
if (window.Prism && typeof window.Prism.highlightElement === 'function'
&& highlighted.get(code) !== text) {
try {
window.Prism.highlightElement(code);
highlighted.set(code, code.textContent);
} catch (e) { /* 元のコード表示を残す。次の再検査で再試行する。 */ }
}
let state = controls.get(wrap);
// HCB側に既存のコピー操作があれば追加しない。
if (wrap.querySelector('.hcb-clipboard')) {
if (state) { state.button.remove(); state.status.remove(); controls.delete(wrap); }
return;
}
if (state) {
state.code = code;
if (!state.button.isConnected) wrap.appendChild(state.button);
if (!state.status.isConnected) wrap.appendChild(state.status);
return;
}
const button = document.createElement('button');
button.type = 'button';
button.className = 'waza-codoc-copy';
button.textContent = 'コードをコピー';
const status = document.createElement('span');
status.setAttribute('role', 'status');
state = { code, button, status };
controls.set(wrap, state);
button.addEventListener('click', async () => {
status.textContent = '';
try {
if (!state.code.isConnected || !navigator.clipboard || !navigator.clipboard.writeText) throw new Error('unavailable');
await navigator.clipboard.writeText(state.code.textContent);
status.textContent = ' コピーしました。';
} catch (e) {
status.textContent = ' コピーできませんでした。コードを選択して手動でコピーしてください。';
}
});
wrap.append(button, status);
});
};
const schedule = () => {
if (pending) return;
pending = true;
requestAnimationFrame(scan);
};
if (typeof MutationObserver !== 'undefined') {
new MutationObserver(records => {
if (records.some(r => (r.target.parentElement && r.target.parentElement.closest('.codoc-entries pre code'))
|| Array.from(r.addedNodes).some(n =>
n.nodeType === 1 && (n.matches('.codoc-entries, .hcb_wrap, pre, code, .hcb-clipboard')
|| n.querySelector('.codoc-entries, .hcb_wrap, pre, code'))))) schedule();
}).observe(document.body, { childList: true, characterData: true, subtree: true });
}
// 外部スクリプトの遅延ロード後にも再検査。
document.addEventListener('load', event => {
if (event.target.tagName === 'SCRIPT') schedule();
}, true);
window.addEventListener('load', schedule, { once: true });
document.addEventListener('waza-codoc-hcb-refresh', schedule);
scan();
};
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, { once: true });
else init();
})();
</script>
<?php
}, 99);
解説
MutationObserverを使って、後から追加される.hcb_wrap要素を検知- 各
.hcb_wrapに対して Prism.js のシンタックスハイライトを適用 - 既存ボタンがない場合だけ独自のコピー操作を追加し、成功・失敗をステータス文で伝える
WeakMapを使って、処理済みコードの文字列とボタンを管理します。初期表示も走査し、後からcode要素が入った場合や置き換わった場合に再検査します
使用上の注意
- 色分けにはPrism本体・言語定義とHCBのCSSが必要です。このコードはライブラリを読み込みません。Prismが使えない場合はコード文字列を残します。コピーはHTTPSなどの安全なコンテキストとブラウザーの許可が必要です。
Highlighting Code Blockプラグインを使用していることが前提です。
まとめ
codocのような非同期読み込みを行うコンテンツでは、テーマやプラグインの初期化タイミングから外れてJSやCSSが効かないブロックが発生することがあります。
この記事で紹介しているコードは、GitHubのMOTOKI-LLC/WAZA-codeにも掲載していますが、今回の修正との同期は未確認です。
2026年10月21日にPHP構文とjsdom上の動的挿入・初期表示・コード差し替え・重複実行・コピー成功/失敗の模擬動作を確認しました。実codocの購入後表示、Prism言語定義の組合せ、実クリップボード、PCスマホ・キーボード・読み上げは未検証です。コード文字列だけを書き換える実装などで再検査されない場合は、追加処理側からdocument.dispatchEvent(new Event(‘waza-codoc-hcb-refresh’))を実行できます。導入前にDOM構造を確認してください。戻す場合は追加コードを停止し、ページを再読み込みします。



