From 742a47eb9d680210191dbb4d1463d762906edcfa Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 19:17:01 +0200 Subject: [PATCH 1/8] Move HTML to page HTML --- lib/experimental/script-modules.php | 48 ++++++++++++++++++---- packages/a11y/CHANGELOG.md | 2 + packages/a11y/src/module/index.ts | 22 ++-------- packages/a11y/src/shared/add-intro-text.ts | 1 - 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index a113df02b9d75..31cbbda4429e5 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -201,6 +201,44 @@ function gutenberg_dequeue_module( $module_identifier ) { wp_script_modules()->dequeue( $module_identifier ); } +/** + * Prints HTML for the a11y Script Module. + * + * a11y relies on some DOM elements to use as ARIA live regions. + * Ideally, these elements are part of the initial HTML of the page + * so that accessibility tools can find them and observe updates. + */ +function gutenberg_a11y_script_module_html() { + $a11y_module_available = false; + + $get_marked_for_enqueue = new ReflectionMethod( 'WP_Script_Modules', 'get_marked_for_enqueue' ); + $get_marked_for_enqueue->setAccessible( true ); + $get_import_map = new ReflectionMethod( 'WP_Script_Modules', 'get_import_map' ); + $get_import_map->setAccessible( true ); + + foreach ( array_keys( $get_marked_for_enqueue->invoke( wp_script_modules() ) ) as $id ) { + if ( '@wordpress/a11y' === $id ) { + $a11y_module_available = true; + break; + } + + } + if ( ! $a11y_module_available ) { + foreach ( array_keys( $get_import_map->invoke( wp_script_modules() )['imports'] ) as $id ) { + if ( '@wordpress/a11y' === $id ) { + $a11y_module_available = true; + break; + } + } + } + if ( ! $a11y_module_available ) { + return; + } + echo '

' . esc_html__( 'Notifications', 'default' ) . '

'; + echo '
'; + echo '
'; +} + /** * Registers Gutenberg Script Modules. * @@ -218,12 +256,8 @@ function gutenberg_register_script_modules() { array(), $default_version ); - add_filter( - 'script_module_data_@wordpress/a11y', - function ( $data ) { - $data['i18n'] = array( 'Notifications' => __( 'Notifications', 'default' ) ); - return $data; - } - ); + + add_action( 'wp_footer', 'gutenberg_a11y_script_module_html' ); + add_action( 'admin_footer', 'gutenberg_a11y_script_module_html' ); } add_action( 'init', 'gutenberg_register_script_modules' ); diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 36973cce020f3..57f9f1e753101 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Remove -webkit-clip-path prefixed CSS property. + ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/a11y/src/module/index.ts b/packages/a11y/src/module/index.ts index a2c87f397f487..eef6ea9755436 100644 --- a/packages/a11y/src/module/index.ts +++ b/packages/a11y/src/module/index.ts @@ -1,25 +1,11 @@ /** * Internal dependencies */ -import { makeSetupFunction } from '../shared/index'; export { speak } from '../shared/index'; -// Without an i18n Script Module, "Notifications" (the only localized text used in this module) -// will be translated on the server and provided as script-module data. -let notificationsText = 'Notifications'; -try { - const textContent = document.getElementById( - 'wp-script-module-data-@wordpress/a11y' - )?.textContent; - if ( textContent ) { - const parsed = JSON.parse( textContent ); - notificationsText = parsed?.i18n?.Notifications ?? notificationsText; - } -} catch {} - /** - * Create the live regions. + * This no-op function is exported to provide compatibility with the `wp-a11y` Script. + * + * The Script Module should include the relevant HTML as part of page load. */ -export const setup = makeSetupFunction( notificationsText ); - -setup(); +export const setup = () => {}; diff --git a/packages/a11y/src/shared/add-intro-text.ts b/packages/a11y/src/shared/add-intro-text.ts index 6bd97c887664d..3d1c9ea18be94 100644 --- a/packages/a11y/src/shared/add-intro-text.ts +++ b/packages/a11y/src/shared/add-intro-text.ts @@ -23,7 +23,6 @@ export default function addIntroText( introTextContent: string ) { 'width: 1px;' + 'overflow: hidden;' + 'clip: rect(1px, 1px, 1px, 1px);' + - '-webkit-clip-path: inset(50%);' + 'clip-path: inset(50%);' + 'border: 0;' + 'word-wrap: normal !important;' From 196e41f1c8d2cd199729f1e0953214f5ecba826a Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 19:36:51 +0200 Subject: [PATCH 2/8] Restructure a11y to separate script and module from core functionality --- packages/a11y/src/index.js | 25 +++++++++++++++-- .../src/{shared => script}/add-container.js | 0 .../src/{shared => script}/add-intro-text.ts | 10 +++++-- .../test/add-container.test.js | 0 packages/a11y/src/shared/index.js | 28 ------------------- 5 files changed, 29 insertions(+), 34 deletions(-) rename packages/a11y/src/{shared => script}/add-container.js (100%) rename packages/a11y/src/{shared => script}/add-intro-text.ts (83%) rename packages/a11y/src/{shared => script}/test/add-container.test.js (100%) diff --git a/packages/a11y/src/index.js b/packages/a11y/src/index.js index 59e93da780bd8..cdc3be1054515 100644 --- a/packages/a11y/src/index.js +++ b/packages/a11y/src/index.js @@ -2,18 +2,37 @@ * WordPress dependencies */ import domReady from '@wordpress/dom-ready'; -import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { makeSetupFunction } from './shared/index'; +import addContainer from './script/add-container'; +import addIntroText from './script/add-intro-text'; + export { speak } from './shared/index'; /** * Create the live regions. */ -export const setup = makeSetupFunction( __( 'Notifications' ) ); +export function setup() { + const introText = document.getElementById( 'a11y-speak-intro-text' ); + const containerAssertive = document.getElementById( + 'a11y-speak-assertive' + ); + const containerPolite = document.getElementById( 'a11y-speak-polite' ); + + if ( introText === null ) { + addIntroText(); + } + + if ( containerAssertive === null ) { + addContainer( 'assertive' ); + } + + if ( containerPolite === null ) { + addContainer( 'polite' ); + } +} /** * Run setup on domReady. diff --git a/packages/a11y/src/shared/add-container.js b/packages/a11y/src/script/add-container.js similarity index 100% rename from packages/a11y/src/shared/add-container.js rename to packages/a11y/src/script/add-container.js diff --git a/packages/a11y/src/shared/add-intro-text.ts b/packages/a11y/src/script/add-intro-text.ts similarity index 83% rename from packages/a11y/src/shared/add-intro-text.ts rename to packages/a11y/src/script/add-intro-text.ts index 3d1c9ea18be94..57b00299adaeb 100644 --- a/packages/a11y/src/shared/add-intro-text.ts +++ b/packages/a11y/src/script/add-intro-text.ts @@ -1,18 +1,22 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + /** * Build the explanatory text to be placed before the aria live regions. * * This text is initially hidden from assistive technologies by using a `hidden` * HTML attribute which is then removed once a message fills the aria-live regions. * - * @param {string} introTextContent The translated intro text content. * @return {HTMLParagraphElement} The explanatory text HTML element. */ -export default function addIntroText( introTextContent: string ) { +export default function addIntroText() { const introText = document.createElement( 'p' ); introText.id = 'a11y-speak-intro-text'; introText.className = 'a11y-speak-intro-text'; - introText.textContent = introTextContent; + introText.textContent = __( 'Notifications' ); introText.setAttribute( 'style', diff --git a/packages/a11y/src/shared/test/add-container.test.js b/packages/a11y/src/script/test/add-container.test.js similarity index 100% rename from packages/a11y/src/shared/test/add-container.test.js rename to packages/a11y/src/script/test/add-container.test.js diff --git a/packages/a11y/src/shared/index.js b/packages/a11y/src/shared/index.js index a05f891f42856..2b6353720d0ad 100644 --- a/packages/a11y/src/shared/index.js +++ b/packages/a11y/src/shared/index.js @@ -1,37 +1,9 @@ /** * Internal dependencies */ -import addContainer from './add-container'; -import addIntroText from './add-intro-text'; import clear from './clear'; import filterMessage from './filter-message'; -/** - * Create the live regions. - * @param {string} introTextContent The intro text content. - */ -export function makeSetupFunction( introTextContent ) { - return function setup() { - const introText = document.getElementById( 'a11y-speak-intro-text' ); - const containerAssertive = document.getElementById( - 'a11y-speak-assertive' - ); - const containerPolite = document.getElementById( 'a11y-speak-polite' ); - - if ( introText === null ) { - addIntroText( introTextContent ); - } - - if ( containerAssertive === null ) { - addContainer( 'assertive' ); - } - - if ( containerPolite === null ) { - addContainer( 'polite' ); - } - }; -} - /** * Allows you to easily announce dynamic interface updates to screen readers using ARIA live regions. * This module is inspired by the `speak` function in `wp-a11y.js`. From c7571232fe2ca14058bc4a4bcf48c9230edc2a98 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 19:37:51 +0200 Subject: [PATCH 3/8] Fix lint --- lib/experimental/script-modules.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 31cbbda4429e5..86cceba0aefb1 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -221,7 +221,6 @@ function gutenberg_a11y_script_module_html() { $a11y_module_available = true; break; } - } if ( ! $a11y_module_available ) { foreach ( array_keys( $get_import_map->invoke( wp_script_modules() )['imports'] ) as $id ) { From 49a095b480c9549c411ba269b56c1cf416202913 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 16 Sep 2024 20:08:55 +0200 Subject: [PATCH 4/8] Revert unrelated change --- packages/a11y/CHANGELOG.md | 2 -- packages/a11y/src/script/add-intro-text.ts | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/a11y/CHANGELOG.md b/packages/a11y/CHANGELOG.md index 57f9f1e753101..36973cce020f3 100644 --- a/packages/a11y/CHANGELOG.md +++ b/packages/a11y/CHANGELOG.md @@ -2,8 +2,6 @@ ## Unreleased -- Remove -webkit-clip-path prefixed CSS property. - ## 4.7.0 (2024-09-05) ## 4.6.0 (2024-08-21) diff --git a/packages/a11y/src/script/add-intro-text.ts b/packages/a11y/src/script/add-intro-text.ts index 57b00299adaeb..2bcf453ec44c8 100644 --- a/packages/a11y/src/script/add-intro-text.ts +++ b/packages/a11y/src/script/add-intro-text.ts @@ -27,6 +27,7 @@ export default function addIntroText() { 'width: 1px;' + 'overflow: hidden;' + 'clip: rect(1px, 1px, 1px, 1px);' + + '-webkit-clip-path: inset(50%);' + 'clip-path: inset(50%);' + 'border: 0;' + 'word-wrap: normal !important;' From 013421e9ecf499c4f0a6ff7ac8c70f334170b9a6 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 17 Sep 2024 12:16:48 +0200 Subject: [PATCH 5/8] Move `style` attribute to container element --- lib/experimental/script-modules.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 86cceba0aefb1..ce873713c3ba7 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -233,9 +233,11 @@ function gutenberg_a11y_script_module_html() { if ( ! $a11y_module_available ) { return; } - echo '

' . esc_html__( 'Notifications', 'default' ) . '

'; - echo '
'; - echo '
'; + echo '
' + . '

' . esc_html__( 'Notifications', 'default' ) . '

' + . '
' + . '
' + . '
'; } /** From 6e5f9b46b379202ccfa97a130a0a96940facaaf9 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 17 Sep 2024 12:21:34 +0200 Subject: [PATCH 6/8] Intro text should be hidden initially --- lib/experimental/script-modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index ce873713c3ba7..93076f488ee4b 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -234,7 +234,7 @@ function gutenberg_a11y_script_module_html() { return; } echo '
' - . '

' . esc_html__( 'Notifications', 'default' ) . '

' + . '' . '
' . '
' . '
'; From b0e67249df90acb2a06c27bc42e2dd1c351fb2df Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 17 Sep 2024 12:37:45 +0200 Subject: [PATCH 7/8] Improve comment --- packages/a11y/src/module/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/a11y/src/module/index.ts b/packages/a11y/src/module/index.ts index eef6ea9755436..a06882f068dd3 100644 --- a/packages/a11y/src/module/index.ts +++ b/packages/a11y/src/module/index.ts @@ -6,6 +6,6 @@ export { speak } from '../shared/index'; /** * This no-op function is exported to provide compatibility with the `wp-a11y` Script. * - * The Script Module should include the relevant HTML as part of page load. + * Filters should inject the relevant HTML on page load instead of requiring setup. */ export const setup = () => {}; From 1ae9ed016804126d87fe44639ba6413375644555 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Tue, 17 Sep 2024 12:47:25 +0200 Subject: [PATCH 8/8] Remove redundant clip rule and minimize style value --- lib/experimental/script-modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/experimental/script-modules.php b/lib/experimental/script-modules.php index 93076f488ee4b..f65bc1704dd89 100644 --- a/lib/experimental/script-modules.php +++ b/lib/experimental/script-modules.php @@ -233,7 +233,7 @@ function gutenberg_a11y_script_module_html() { if ( ! $a11y_module_available ) { return; } - echo '
' + echo '
' . '' . '
' . '
'