Skip to content

Prosopo Procaptcha: guard against wpautop hoisting captcha children out of the custom element - #853

Merged
dannyvankooten merged 1 commit into
ibericode:mainfrom
prosopo:prosopo-procaptcha-wpautop-fallback
Aug 13, 2026
Merged

Prosopo Procaptcha: guard against wpautop hoisting captcha children out of the custom element#853
dannyvankooten merged 1 commit into
ibericode:mainfrom
prosopo:prosopo-procaptcha-wpautop-fallback

Conversation

@forgetso

@forgetso forgetso commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

The <mc4wp-procaptcha> custom element's setup() calls this.querySelector('.mc4wp-procaptcha__captcha') and passes the result straight to window.procaptcha.render(...). If the custom element ends up wrapped in a <p> (as it does under wpautop, or in many themes that filter form content), the browser's HTML parser auto-closes that <p> before the child <div> — block-level content is not permitted inside <p> — and hoists the captcha container out to become a sibling.

Result: querySelector returns null, render(null, …) throws a TypeError: Cannot read properties of null (reading 'tagName'), and the page's other JavaScript stops running.

Reproduced on gilliancooper.co.uk (Flatsome + LiteSpeed Cache). The problem has been latent since the integration shipped in October 2024; it only surfaces when the surrounding markup wraps the custom element in a <p>.

Fix

In setup():

  • Fall back to the enclosing <form> when the local querySelector returns null, for both the captcha container and the validation error element.
  • Skip rendering with a console.warn rather than crashing if the container is genuinely missing.
  • Only attach the submit handler when a form is actually present.

The plugin's PHP-side markup is already correct — this is purely defensive against downstream markup post-processing.

Test plan

  • Load a form with the default PHP-emitted markup (custom element and its <div> child intact) — widget renders as before.
  • Load a form whose surrounding template wraps the field stub in a <p> (or run the content through wpautop) — widget renders using the sibling <div> instead of crashing.
  • Confirm no console errors under the healthy case.

…ment

Some themes (and any content path that applies `wpautop`) wrap the
`<mc4wp-procaptcha>` custom element in a `<p>`. The HTML parser then
auto-closes that `<p>` before the child `<div class="mc4wp-procaptcha__captcha">`
— block-level content is not allowed inside `<p>` — hoisting the container
out as a sibling. `this.querySelector('.mc4wp-procaptcha__captcha')` returns
null, `window.procaptcha.render(null, …)` throws, and the page's other JS
stops running.

Walk to the enclosing `<form>` when the local query returns null, and skip
rendering with a console warning rather than crashing if the container is
truly absent.

Reported on gilliancooper.co.uk (Flatsome + LiteSpeed). Latent since the
integration shipped; only manifests when the surrounding markup wraps the
custom element in a `<p>`.
@dannyvankooten
dannyvankooten merged commit 75b522d into ibericode:main Aug 13, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants