From 190a21756dec0d36e39a60ce7f989c1451ef7dd5 Mon Sep 17 00:00:00 2001 From: Aagam Shah Date: Tue, 26 May 2026 15:54:07 +0530 Subject: [PATCH] Content Guidelines AI: update injection selectors for latest Gutenberg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Gutenberg Guidelines page markup changed in two ways that broke the AI UI injection (silently — the bundle loaded with no console error but nothing rendered): - content-guidelines__* classes were renamed to guidelines__*. - The accordion was refactored to CollapsibleCard (hashed CSS-module classes) and the per-section element id was removed. Update lib/inject.js to anchor on stable selectors: - Per-section badge/actions/button now key off the new `data-slug` attribute on `.guidelines__list-item`, plus semantic anchors (form, submit button) within each section. - Banner / upgrade notice use the renamed `.guidelines__list`. - The header "Suggest all" button moves to the top of `.guidelines__content` (the wp-admin Page header renders no actions slot since the page passes no `actions`). The block-guideline modal selectors are unchanged. Depends on the Gutenberg `data-slug` hook. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../_inc/content-guidelines-ai/lib/inject.js | 56 +++++++++++-------- ...-content-guidelines-ai-gutenberg-selectors | 4 ++ 2 files changed, 37 insertions(+), 23 deletions(-) create mode 100644 projects/plugins/jetpack/changelog/update-content-guidelines-ai-gutenberg-selectors diff --git a/projects/plugins/jetpack/_inc/content-guidelines-ai/lib/inject.js b/projects/plugins/jetpack/_inc/content-guidelines-ai/lib/inject.js index b826ca0fe75e..015d62efdaa9 100644 --- a/projects/plugins/jetpack/_inc/content-guidelines-ai/lib/inject.js +++ b/projects/plugins/jetpack/_inc/content-guidelines-ai/lib/inject.js @@ -100,13 +100,21 @@ function getBlockNameFromModal( modal ) { } function runAll() { - // Header button. + // Header button — placed at the top of the guidelines content, above the + // list. The wp-admin Page header only renders an actions slot when the + // gutenberg page passes `actions` to (it does not), so there is no + // header-actions container to target. inject( 'header', () => { - const actionsSlot = document.querySelector( '.admin-ui-page__header-actions' ); - return actionsSlot - ? { parent: actionsSlot, className: 'jetpack-content-guidelines-ai__header-container' } + const content = document.querySelector( '.guidelines__content' ); + const list = content?.querySelector( '.guidelines__list' ); + return content + ? { + parent: content, + before: list, + className: 'jetpack-content-guidelines-ai__header-container', + } : null; }, SuggestAllButton @@ -116,7 +124,7 @@ function runAll() { inject( 'upgrade-notice', () => { - const list = document.querySelector( '.content-guidelines__list' ); + const list = document.querySelector( '.guidelines__list' ); return list ? { parent: list.parentElement, @@ -132,7 +140,7 @@ function runAll() { inject( 'banner', () => { - const list = document.querySelector( '.content-guidelines__list' ); + const list = document.querySelector( '.guidelines__list' ); return list ? { parent: list.parentElement, @@ -144,29 +152,30 @@ function runAll() { EmptyStateBanner ); - // Per-section injections. + // Per-section injections. Sections are matched by the stable `data-slug` + // attribute on each `.guidelines__list-item`. The per-section form is + // always present in the DOM (the CollapsibleCard keeps its content mounted + // while collapsed). for ( const slug of VALID_SECTIONS ) { - const form = document.getElementById( `content-guidelines-${ slug }` ); + const item = document.querySelector( `.guidelines__list-item[data-slug="${ slug }"]` ); + const form = item?.querySelector( 'form' ); if ( ! form ) { continue; } - // Badge in accordion header. + // Badge in the accordion header (the section's heading element). inject( `badge-${ slug }`, () => { - const accordion = form.closest( '.content-guidelines__accordion' ); - const trigger = accordion?.querySelector( '.content-guidelines__accordion-trigger' ); - const hStack = trigger?.firstElementChild; - if ( ! hStack ) { - return null; - } - return { - parent: hStack, - before: hStack.lastElementChild, - className: 'jetpack-content-guidelines-ai__badge-container', - tag: 'span', - }; + const heading = item.querySelector( 'h1, h2, h3, h4, h5, h6' ); + const titleStack = heading?.firstElementChild ?? heading; + return titleStack + ? { + parent: titleStack, + className: 'jetpack-content-guidelines-ai__badge-container', + tag: 'span', + } + : null; }, SuggestionBadge, { slug } @@ -189,11 +198,12 @@ function runAll() { { slug } ); - // Per-section generate button next to save. + // Per-section generate button next to the Save button (the form's + // primary submit button lives in an HStack with the Clear button). inject( `button-${ slug }`, () => { - const saveButton = form.querySelector( '.save-button' ); + const saveButton = form.querySelector( 'button[type="submit"]' ); const hStack = saveButton?.parentElement; return hStack ? { diff --git a/projects/plugins/jetpack/changelog/update-content-guidelines-ai-gutenberg-selectors b/projects/plugins/jetpack/changelog/update-content-guidelines-ai-gutenberg-selectors new file mode 100644 index 000000000000..59530dc8376c --- /dev/null +++ b/projects/plugins/jetpack/changelog/update-content-guidelines-ai-gutenberg-selectors @@ -0,0 +1,4 @@ +Significance: patch +Type: bugfix + +Content Guidelines AI: update DOM selectors to match the latest Gutenberg Guidelines markup so the AI UI injects correctly.