(bool) $f['skip_link'], 'skipTarget' => (string) $f['skip_target'], 'labels' => (bool) $f['form_labels'], 'zoom' => (bool) $f['zoom'], 'newWindow' => (string) $f['new_window'], 'tabindex' => (bool) $f['tabindex'], 'lang' => $f['lang_dir'] ? str_replace( '_', '-', get_bloginfo( 'language' ) ) : '', 'dir' => $f['lang_dir'] ? ( is_rtl() ? 'rtl' : 'ltr' ) : '', 'emptySearch' => (bool) $f['empty_search'], 'i18n' => array( 'skip' => __( 'Skip to content', 'ariaccess' ), 'newTab' => __( '(opens in a new tab)', 'ariaccess' ), 'search' => __( 'Search', 'ariaccess' ), 'emptySearch' => __( 'Please type something to search for.', 'ariaccess' ), ), ); } /** * Enqueue the fixes CSS and script. */ public static function enqueue() { $f = AriAccess_Settings::get( 'fixes' ); $css = '.ariaccess-sr{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}'; if ( $f['skip_link'] ) { $css .= '.ariaccess-skip{position:absolute;left:12px;top:-200px;z-index:2147483647;padding:12px 18px;background:#fff;color:#111;font:600 16px/1.2 system-ui,sans-serif;border:3px solid #111;border-radius:6px;text-decoration:underline}.ariaccess-skip:focus{top:12px;outline:3px solid ' . esc_attr( $f['focus_color'] ) . ';outline-offset:2px}'; } if ( $f['focus_outline'] ) { $css .= ':where(a,button,input,select,textarea,summary,[tabindex],[contenteditable]):focus-visible{outline:3px solid ' . esc_attr( $f['focus_color'] ) . '!important;outline-offset:2px!important;box-shadow:0 0 0 5px #fff!important}'; } if ( $f['underline_links'] ) { $css .= ':where(.entry-content,.wp-block-post-content,.post-content,article) p a,:where(.entry-content,.wp-block-post-content,.post-content,article) li a{text-decoration:underline!important;text-underline-offset:.15em}'; } if ( $f['reduced_motion'] ) { $css .= '@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}}'; } if ( $f['empty_search'] ) { $css .= '.ariaccess-search-error{display:block;margin:.4em 0;padding:.4em .6em;background:#fff;color:#b00020;border-left:4px solid #b00020;font-weight:600}'; } wp_register_style( 'ariaccess-fixes', false, array(), ARIACCESS_VERSION ); wp_enqueue_style( 'ariaccess-fixes' ); wp_add_inline_style( 'ariaccess-fixes', $css ); $needs_js = $f['skip_link'] || $f['form_labels'] || $f['zoom'] || 'off' !== $f['new_window'] || $f['tabindex'] || $f['lang_dir'] || $f['empty_search']; if ( $needs_js ) { wp_enqueue_script( 'ariaccess-fixes', ARIACCESS_URL . 'assets/js/fixes.js', array(), ARIACCESS_VERSION, array( 'strategy' => 'defer', 'in_footer' => true ) ); wp_add_inline_script( 'ariaccess-fixes', 'window.ariaccessFixes=' . wp_json_encode( self::js_config() ) . ';', 'before' ); } } /** * Print the skip link at the top of the body. */ public static function skip_link() { $target = (string) AriAccess_Settings::get( 'fixes', 'skip_target' ); $href = ( '' !== $target && '#' === $target[0] && preg_match( '/^#[\w-]+$/', $target ) ) ? $target : '#main'; printf( '%s', esc_attr( $href ), esc_html__( 'Skip to content', 'ariaccess' ) ); } /** * Fill missing or empty alt text on library images from the Media Library. * * The block editor copies alt text into the post when an image is inserted, so alt text * added to the Media Library later never reaches older posts. This fills the gap. * * @param string $html Content. * @return string */ public static function fill_media_alt( $html ) { if ( false === strpos( (string) $html, 'wp-image-' ) ) { return $html; } return preg_replace_callback( '/]*>/i', function ( $m ) { $tag = $m[0]; if ( ! preg_match( '/\bwp-image-(\d+)\b/', $tag, $id ) ) { return $tag; } if ( preg_match( '/\brole=["\'](presentation|none)["\']|\baria-hidden=["\']true["\']/i', $tag ) ) { return $tag; } $has_alt = preg_match( '/\salt=(["\'])(.*?)\1/is', $tag, $alt ); if ( $has_alt && '' !== trim( $alt[2] ) ) { return $tag; } $library = trim( (string) get_post_meta( (int) $id[1], '_wp_attachment_image_alt', true ) ); if ( '' === $library ) { return $tag; } $attr = 'alt="' . esc_attr( $library ) . '"'; if ( $has_alt ) { return preg_replace( '/\salt=(["\'])(.*?)\1/is', $attr, $tag, 1 ); } return preg_replace( '/^]*?)\s+title=(["\']).*?\2/i', '$1', (string) $html ); return preg_replace_callback( '/]*?)\s+title=(["\'])(.*?)\2([^>]*)>(.*?)<\/a>/is', function ( $m ) { $title = trim( wp_strip_all_tags( html_entity_decode( $m[3], ENT_QUOTES, 'UTF-8' ) ) ); $text = trim( wp_strip_all_tags( html_entity_decode( $m[5], ENT_QUOTES, 'UTF-8' ) ) ); if ( '' !== $text && 0 === strcasecmp( $title, $text ) ) { return '' . $m[5] . ''; } return $m[0]; }, $html ); } /** * Tag clouds: the count tooltip duplicates the aria-label. * * @param array $tags Tag data. * @return array */ public static function tag_cloud( $tags ) { foreach ( $tags as &$tag ) { $tag['title'] = ''; } return $tags; } /** * Remove target="_blank" from content links. * * @param string $html Content. * @return string */ public static function remove_targets( $html ) { return preg_replace( '/(]*?)\s+target=(["\'])_blank\2/i', '$1', (string) $html ); } /** * "Read more" link with the post title for screen readers. * * @param string $link Link HTML. * @return string */ public static function more_link( $link ) { if ( AriAccess_Checker::$rendering || false !== strpos( $link, 'ariaccess-sr' ) || false !== strpos( $link, 'screen-reader-text' ) ) { return $link; } $title = get_the_title(); if ( '' === $title ) { return $link; } return preg_replace( '/<\/a>/', ': ' . esc_html( wp_strip_all_tags( $title ) ) . '', $link, 1 ); } /** * Excerpt "more" links with context. * * @param string $more More text/link. * @return string */ public static function excerpt_more( $more ) { if ( false === strpos( (string) $more, '' ) ) { return $more; } return self::more_link( $more ); } /** * Search forms without a label get one. * * @param string $form Form HTML. * @return string */ public static function search_form( $form ) { if ( false !== stripos( $form, ']*\bname=(["\'])s\1)/i', '