diff --git a/.github/workflows/deploy-on-release-to-dot-org.yml b/.github/workflows/deploy-on-release-to-dot-org.yml
index 873f921a..5f2f941d 100644
--- a/.github/workflows/deploy-on-release-to-dot-org.yml
+++ b/.github/workflows/deploy-on-release-to-dot-org.yml
@@ -45,14 +45,3 @@ jobs:
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
BUILD_DIR: ./dist/${{ github.event.repository.name }}/
-
- - name: Upload release asset
- if: github.event.release # can only run in context of a release
- uses: actions/upload-release-asset@v1
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- with:
- upload_url: ${{ github.event.release.upload_url }}
- asset_path: ${{ steps.dist-build.outputs.zip-path }}
- asset_name: ${{ github.event.repository.name }}.zip
- asset_content_type: application/zip
diff --git a/accessibility-checker.php b/accessibility-checker.php
index 4b306af5..8a6de117 100755
--- a/accessibility-checker.php
+++ b/accessibility-checker.php
@@ -10,7 +10,7 @@
* Plugin Name: Accessibility Checker
* Plugin URI: https://a11ychecker.com
* Description: Audit and check your website for accessibility before you hit publish. In-post accessibility scanner and guidance.
- * Version: 1.11.2
+ * Version: 1.12.0
* Author: Equalize Digital
* Author URI: https://equalizedigital.com
* License: GPL-2.0+
@@ -35,7 +35,7 @@
// Current plugin version.
if ( ! defined( 'EDAC_VERSION' ) ) {
- define( 'EDAC_VERSION', '1.11.2' );
+ define( 'EDAC_VERSION', '1.12.0' );
}
// Current database version.
@@ -149,6 +149,17 @@ function edac_register_rules() {
// If we got this far, this is the 1st time we called this function.
// We need to load the rules from the filesystem, and apply any filters.
$default_rules = include __DIR__ . '/includes/rules.php';
+ /**
+ * Filter the default rules.
+ *
+ * Allows removing or adding rules. If you are adding a rule make
+ * sure you have added a function matching the pattern:
+ * `edac_rule_{$rule_id}`.
+ *
+ * @since 1.4.0
+ *
+ * @param array $default_rules The default rules.
+ */
$default_rules = apply_filters( 'edac_filter_register_rules', $default_rules );
return $default_rules;
diff --git a/admin/class-admin-notices.php b/admin/class-admin-notices.php
index 13615b5a..0e876912 100644
--- a/admin/class-admin-notices.php
+++ b/admin/class-admin-notices.php
@@ -350,6 +350,13 @@ public function edac_review_notice_ajax() {
* @return string
*/
public function edac_password_protected_notice_text() {
+ /**
+ * Filter the password protected notice text.
+ *
+ * @since 1.4.0
+ *
+ * @param string $text The password protected notice text.
+ */
return apply_filters(
'edac_filter_password_protected_notice_text',
sprintf(
diff --git a/admin/class-ajax.php b/admin/class-ajax.php
index a6c710fe..1fff9869 100644
--- a/admin/class-ajax.php
+++ b/admin/class-ajax.php
@@ -290,6 +290,13 @@ function ( $a, $b ) {
$rules = array_merge( $error_rules, $warning_rules, $passed_rules );
if ( $rules ) {
+ /**
+ * Filters if a user can ignore issues.
+ *
+ * @since 1.4.0
+ *
+ * @allowed bool True if allowed, false if not
+ */
$ignore_permission = apply_filters( 'edac_ignore_permission', true );
foreach ( $rules as $rule ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Using direct query for interacting with custom database, safe variable used for table name, caching not required for one time operation.
@@ -509,6 +516,14 @@ public function readability() {
}
}
+ /**
+ * Filter the content used for reading grade readability analysis.
+ *
+ * @since 1.4.0
+ *
+ * @param string $content The content to be filtered.
+ * @param int $post_id The post ID.
+ */
$content = apply_filters( 'edac_filter_readability_content', $content, $post_id );
$content = wp_filter_nohtml_kses( $content );
$content = str_replace( ']]>', ']]>', $content );
diff --git a/admin/class-insert-rule-data.php b/admin/class-insert-rule-data.php
index 1c7c1da0..db15a381 100644
--- a/admin/class-insert-rule-data.php
+++ b/admin/class-insert-rule-data.php
@@ -110,7 +110,15 @@ public function insert( object $post, string $rule, string $ruletype, string $ru
// Insert new records.
if ( ! $results ) {
- // filter post types.
+ /**
+ * Filter the rule data before inserting it into the database.
+ *
+ * This data will be sanitized after the filter is applied.
+ *
+ * @since 1.4.0
+ *
+ * @param array $rule_data The rule data.
+ */
$rule_data = apply_filters( 'edac_filter_insert_rule_data', $rule_data );
// Sanitize rule data since it is filtered, and we can't be sure
diff --git a/admin/class-meta-boxes.php b/admin/class-meta-boxes.php
index a97b4f05..727ef192 100644
--- a/admin/class-meta-boxes.php
+++ b/admin/class-meta-boxes.php
@@ -54,8 +54,18 @@ public function register_meta_boxes(): void {
* @return void
*/
public function render(): void {
+ /**
+ * Fires before the meta box is rendered.
+ *
+ * @since 1.10.0
+ */
do_action( 'edac_before_meta_box' );
include_once plugin_dir_path( __DIR__ ) . 'partials/custom-meta-box.php';
+ /**
+ * Fires after the meta box is rendered.
+ *
+ * @since 1.10.0
+ */
do_action( 'edac_after_meta_box' );
}
}
diff --git a/admin/class-scans-stats.php b/admin/class-scans-stats.php
index f90b4357..e7be48ef 100644
--- a/admin/class-scans-stats.php
+++ b/admin/class-scans-stats.php
@@ -317,6 +317,8 @@ function ( $item ) {
$formatting['passed_percentage_formatted'] = Helpers::format_percentage( $data['passed_percentage'] );
$formatting['avg_issue_density_percentage_formatted'] = Helpers::format_percentage( $data['avg_issue_density_percentage'] );
+ $formatting['cached_at_formatted'] = Helpers::format_date( $data['cached_at'], true );
+
$data = array_merge( $data, $formatting );
if ( $data['posts_scanned'] > 0 ) {
diff --git a/admin/class-welcome-page.php b/admin/class-welcome-page.php
index 58414f5d..07e82939 100644
--- a/admin/class-welcome-page.php
+++ b/admin/class-welcome-page.php
@@ -207,7 +207,7 @@ public static function render_summary() {
0 ) : ?>
-
+
diff --git a/admin/site-health/class-information.php b/admin/site-health/class-information.php
index aba1cacc..54bb40ec 100644
--- a/admin/site-health/class-information.php
+++ b/admin/site-health/class-information.php
@@ -18,7 +18,7 @@ class Information {
*/
public function __construct() {
}
-
+
/**
* Initialize class hooks.
*
@@ -63,7 +63,15 @@ private function get_edac_data() {
$information[ $key ] = $class->get();
}
- // Allow extensions to add their own debug information that's specific to EDAC.
+ /**
+ * Filter the debug information.
+ *
+ * Allows extensions to add their own debug information that's specific to EDAC.
+ *
+ * @since 1.6.10
+ *
+ * @param array $information The debug information.
+ */
return apply_filters( 'edac_debug_information', $information );
}
}
diff --git a/changelog.txt b/changelog.txt
index 825bdd58..036f0e41 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,39 @@
Newer versions can be found in readme.txt.
+= 1.9.3 =
+* Updated: capability checks for the welcome page, dashboard widget, and admin notices
+
+= 1.9.2 =
+* Fixed: filtered rules are not passed to the frontend highlighter, avoiding 'null' state issues
+* Updated: frontend highlighter buttons to be disabled until issues are confirmed
+* Updated: frontend highlighter buttons to show only after we know there are issues to display
+* Updated: frontend highlighter to not show buttons if none are returned
+
+= 1.9.1 =
+* Updated: `edac_include_rules_files to fire on init action to fix the `edac_filter_register_rules` filter timing
+
+= 1.9.0 =
+* Created: class that creates the accessibility statement on activation
+* Removed: custom database query that checked for existing accessibility statement in exchange for the `get_page_by_path()` function
+* Fixed: bug with trying to compare the simplified summary ordinal value and added fallback
+* Removed: `wp_send_json_error()` from `simplified_summary` Ajax function when the simplified summary is empty
+* Added: simplified summary grade*level, message, and icon logic to the `summary()` Ajax
+* Fixed: issue with the submit button text showing as `Submit Query` in Firefox.
+* Updated: missing transcript rule to skip certain types of links
+* Added: missing UTM parameters to the welcome page URLs.
+* Removed: legacy system information code
+* Removed: cbschuld/browser.php composer package
+* Added: class structure for site health
+* Added: site health health information for free, pro, and audit history plugins
+* Added: update database class
+* Removed: `edac_before_page_render` functions from the main file
+* Added: frontend validate class
+* Added: frontend validate unit tests
+* Removed: unused new window warning meta update functions
+* Fixed: front end highlight focus issue
+* Added: summary generator class to replace the `edac_summary()` function
+* Deprecated: `edac_summary()` function
+
= 1.8.1 =
* Fixed: false positives on the incorrect heading order rule
* Added: fallback to determine ordinal when php intl extension is not installed
diff --git a/includes/classes/class-rest-api.php b/includes/classes/class-rest-api.php
index 6cc5a92f..e1a93e03 100644
--- a/includes/classes/class-rest-api.php
+++ b/includes/classes/class-rest-api.php
@@ -204,6 +204,16 @@ public function set_post_scan_results( $request ) {
try {
+ /**
+ * Fires before the validation process starts.
+ *
+ * This is only running in the JS check context.
+ *
+ * @since 1.5.0
+ *
+ * @param int $post_id The post ID.
+ * @param string $type The type of validation which is always 'js' in this path.
+ */
do_action( 'edac_before_validate', $post_id, 'js' );
$violations = $request['violations'];
@@ -234,16 +244,48 @@ public function set_post_scan_results( $request ) {
//phpcs:ignore Generic.Commenting.Todo.TaskFound, Squiz.PHP.CommentedOutCode.Found
// TODO: add support storing $violation['selector'], $violation['tags'].
+ /**
+ * Fires before a rule is run against the content.
+ *
+ * This is only running in the JS check context.
+ *
+ * @since 1.5.0
+ *
+ * @param int $post_id The post ID.
+ * @param string $rule_id The rule ID.
+ * @param string $type The type of validation which is always 'js' in this path.
+ */
do_action( 'edac_before_rule', $post_id, $rule_id, 'js' );
( new Insert_Rule_Data() )->insert( $post, $rule_id, $impact, $html );
+ /**
+ * Fires after a rule is run against the content.
+ *
+ * This is only running in the JS check context.
+ *
+ * @since 1.5.0
+ *
+ * @param int $post_id The post ID.
+ * @param string $rule_id The rule ID.
+ * @param string $type The type of validation which is always 'js' in this path.
+ */
do_action( 'edac_after_rule', $post_id, $rule_id, 'js' );
}
}
}
+ /**
+ * Fires after the validation process is complete.
+ *
+ * This is only running in the JS check context.
+ *
+ * @since 1.5.0
+ *
+ * @param int $post_id The post ID.
+ * @param string $type The type of validation which is always 'js' in this path.
+ */
do_action( 'edac_after_validate', $post_id, 'js' );
// remove corrected records.
diff --git a/includes/classes/class-simplified-summary.php b/includes/classes/class-simplified-summary.php
index 64b822e0..71d1fe71 100644
--- a/includes/classes/class-simplified-summary.php
+++ b/includes/classes/class-simplified-summary.php
@@ -58,9 +58,16 @@ public function output_simplified_summary( $content ) {
*/
public function simplified_summary_markup( $post ) {
$simplified_summary = get_post_meta( $post, '_edac_simplified_summary', true )
- ? get_post_meta( $post, '_edac_simplified_summary', true )
+ ? get_post_meta( $post, '_edac_simplified_summary', true )
: '';
+ /**
+ * Filter the heading that gets output before the simplified summary inside an
tag.
+ *
+ * @since 1.4.0
+ *
+ * @param string $simplified_summary_heading The simplified summary heading.
+ */
$simplified_summary_heading = apply_filters(
'edac_filter_simplified_summary_heading',
esc_html__( 'Simplified Summary', 'accessibility-checker' )
diff --git a/includes/helper-functions.php b/includes/helper-functions.php
index 64a3570a..edd5c4b3 100644
--- a/includes/helper-functions.php
+++ b/includes/helper-functions.php
@@ -286,6 +286,13 @@ function edac_custom_post_types() {
* @return array
*/
function edac_post_types() {
+ /**
+ * Filter the post types that the plugin will check.
+ *
+ * @since 1.4.0
+ *
+ * @param array $post_types post types.
+ */
$post_types = apply_filters( 'edac_filter_post_types', [ 'post', 'page' ] );
// remove duplicates.
diff --git a/includes/options-page.php b/includes/options-page.php
index 820d8831..b3c7360e 100644
--- a/includes/options-page.php
+++ b/includes/options-page.php
@@ -50,7 +50,13 @@ function edac_add_options_page() {
return;
}
- // settings panel filter.
+ /**
+ * Filter the capability required to access the settings page.
+ *
+ * @since 1.4.0
+ *
+ * @param string $settings_capability The capability required to access the settings page.
+ */
$settings_capability = apply_filters( 'edac_filter_settings_capability', 'manage_options' );
add_submenu_page(
diff --git a/includes/rules/color_contrast_failure.php b/includes/rules/color_contrast_failure.php
deleted file mode 100644
index 2c572b9a..00000000
--- a/includes/rules/color_contrast_failure.php
+++ /dev/null
@@ -1,724 +0,0 @@
-find( '*' );
- foreach ( $elements as $element ) {
-
- if ( isset( $element ) && stristr( $element->getAttribute( 'style' ), 'color:' ) && '' !== $element->innertext ) {
- $foreground = '';
- $background = '';
-
- // get background color.
- preg_match( '/background-color:\s*(#(?:[0-9a-f]{2}){2,4}|#[0-9a-f]{3}|(?:rgba?|hsla?)\((?:\d+%?(?:deg|rad|grad|turn)?(?:,|\s)+){2,3}[\s\/]*[\d\.]+%?\)\s*(!important)*)/i', $element->getAttribute( 'style' ), $matches, PREG_OFFSET_CAPTURE );
- if ( isset( $matches[1][0] ) && '' !== $matches[1][0] ) {
- $rules['background-color'] = $matches[1][0];
- }
-
- preg_match( '/background:\s*(rgb\(\s*\d{1,3},\s*\d{1,3},\s*\d{1,3}\)|\#*[\w]{3,25}\s*(!important)*)/i', $element->getAttribute( 'style' ), $matches, PREG_OFFSET_CAPTURE );
-
- if ( isset( $matches[1][0] ) && '' !== $matches[1][0] ) {
- $rules['background'] = $matches[1][0];
- }
-
- // if no background color is set assume white.
- $assumedbackground = '#ffffff';
- if ( ! isset( $rules ) && '' !== $assumedbackground ) {
- $rules['background'] = $assumedbackground;
- }
-
- if ( isset( $rules ) ) {
-
- // reverse array if background color is before background.
- if ( strpos( $element->getAttribute( 'style' ), 'background-color:' ) > strpos( $element->getAttribute( 'style' ), 'background:' ) ) {
- $rules = array_reverse( $rules );
- }
-
- $preference = edac_deteremine_hierarchy( $rules );
-
- if ( 'background' === $preference ) {
- $background = edac_check_color_match2( $rules['background'] );
- } elseif ( 'background-color' === $preference ) {
- $background = $rules['background-color'];
- } else {
- return 1;
- }
-
- // get foreground color.
- preg_match( '/[\s|\"|\']*[^-]color:\s*(#(?:[0-9a-f]{2}){2,4}|#[0-9a-f]{3}|(?:rgba?|hsla?)\((?:\d+%?(?:deg|rad|grad|turn)?(?:,|\s)+){2,3}[\s\/]*[\d\.]+%?\)\s*(!important)*)/i', ' ' . $element->getAttribute( 'style' ), $matches, PREG_OFFSET_CAPTURE );
-
- if ( isset( $matches[1][0] ) && '' !== $matches[1][0] ) {
- $foreground = $matches[1][0];
- }
-
- // get font size.
- $font_size = null;
-
- if ( stristr( $element->getAttribute( 'style' ), 'font-size:' ) ) {
-
- $fontsearchpatterns[] = '|font\-size:\s?([\d]+)pt|i';
- $fontsearchpatterns[] = '|font\-size:\s?([\d]+)px|i';
- $fontsearchpatterns[] = '|font:\s?[\w\s\d*\s]*([\d]+)pt|i';
- $fontsearchpatterns[] = '|font:\s?[\w\s\d*\s]*([\d]+)px|i';
-
- // Get font size.
- // 1 px = 0.75 point; 1 point = 1.333333 px.
- foreach ( $fontsearchpatterns as $pattern ) {
- if ( preg_match_all( $pattern, $element, $matches, PREG_PATTERN_ORDER ) ) {
- $matchsize = count( $matches );
- for ( $i = 0; $i < $matchsize; $i++ ) {
- if ( isset( $matches[0][ $i ] ) && '' !== $matches[0][ $i ] ) {
- $absolute_fontsize_errorcode = htmlspecialchars( $matches[0][ $i ] );
-
- preg_match_all( '!\d+!', $absolute_fontsize_errorcode, $matches );
-
- // convert pixels to points.
- if ( stristr( $absolute_fontsize_errorcode, 'px' ) === 'px' ) {
- $font_size = implode( ' ', $matches[0] ) * 0.75;
- }
-
- if ( stristr( $absolute_fontsize_errorcode, 'pt' ) === 'pt' ) {
- $font_size = implode( ' ', $matches[0] );
- }
- }
- }
- }
- }
- }
-
- // get font weight.
- $font_bold = false;
-
- if (
- preg_match( '(bold|bolder|700|800|900)', stristr( $element->getAttribute( 'style' ), 'font-weight:' ) ) === 1 ||
- $element->find( 'b' ) ||
- $element->find( 'strong' )
- ) {
- $font_bold = true;
- }
-
- // ratio.
- $ratio = 4.5;
- if ( ( $font_size >= 14 && true === $font_bold ) || $font_size >= 18 ) {
- $ratio = 3;
- }
-
- if ( '' !== $foreground && 'initial' !== $background && 'inherit' !== $background && 'transparent' !== $background ) {
-
- if ( edac_coldiff( $foreground, $background, $ratio ) ) {
-
- $errors[] = $element->outertext;
- }
- }
- }
- }
- }
-
- // check styles.
- if ( $content['css_parsed'] ) {
- $errors = array_merge( edac_check_contrast( $content ), $errors );
- }
-
- return $errors;
-}
-
-/**
- * Scan the content from a css file or style tag inside a post
- *
- * @param array $content to be checked.
- * @return array
- */
-function edac_check_contrast( $content ) {
- $dom = $content['html'];
- $errors = [];
- $error_code = '';
- $css_array = $content['css_parsed'];
-
- foreach ( $css_array as $element => $rules ) {
-
- if ( array_key_exists( 'color', $rules ) ) {
-
- $background = '';
- $foreground = edac_replace_css_variables( $rules['color'], $css_array );
-
- // determin which rule has preference if both background and background-color are present.
- $preference = edac_deteremine_hierarchy( $rules );
-
- if ( array_key_exists( 'background', $rules ) && 'background' === $preference ) {
- $rules['background'] = edac_replace_css_variables( $rules['background'], $css_array );
- $background = edac_check_color_match2( $rules['background'] );
- }
-
- if ( array_key_exists( 'background-color', $rules ) && 'background-color' === $preference ) {
- $rules['background-color'] = edac_replace_css_variables( $rules['background-color'], $css_array );
- $background = $rules['background-color'];
- }
-
- // if background color not set exit.
- if ( 'initial' === $background || 'inherit' === $background || 'transparent' === $background || '' === $background || '' === $foreground ) {
- continue;
- }
-
- // get font size.
- $font_size = 0;
-
- if ( array_key_exists( 'font-size', $rules ) ) {
-
- $rules['font-size'] = edac_replace_css_variables( $rules['font-size'], $css_array );
-
- $unit = str_replace( '.', '', preg_replace( '/\d/', '', $rules['font-size'] ) );
- $value = str_replace( $unit, '', $rules['font-size'] );
-
- if ( 'px' === $unit ) {
- $font_size = (float) $value * 0.75;
- }
-
- if ( 'pt' === $unit ) {
- $font_size = $value;
- }
- }
-
- // get font weight.
- $font_bold = false;
-
- if ( array_key_exists( 'font-weight', $rules ) ) {
-
- $rules['font-weight'] = edac_replace_css_variables( $rules['font-weight'], $css_array );
-
- if (
- 'bold' === $rules['font-weight'] ||
- 'bolder' === $rules['font-weight'] ||
- '700' === $rules['font-weight'] ||
- '800' === $rules['font-weight'] ||
- '900' === $rules['font-weight']
- ) {
- $font_bold = true;
- }
- }
-
- // check for bold or strong tags within element.
- $bold_elements = $dom->find( $element );
- if ( $bold_elements ) {
- foreach ( $bold_elements as $bold_element ) {
- if ( $bold_element->find( 'b' ) || $bold_element->find( 'strong' ) ) {
- $font_bold = true;
- }
- }
- }
-
- // ratio.
- $ratio = 4.5;
- if ( ( $font_size >= 14 && true === $font_bold ) || $font_size >= 18 ) {
- $ratio = 3;
- }
-
- if ( edac_coldiff( $foreground, $background, $ratio ) ) {
-
- $error_code = $element . ' { ';
- foreach ( $rules as $key => $value ) {
- $error_code .= $key . ': ' . $value . '; ';
- }
- $error_code .= '}';
-
- $els = $dom->find( '*[' . $element . ']' );
- if ( $els ) {
- foreach ( $els as $el ) {
- $errors[] = $el->outertext . ' ' . $error_code;
- }
- }
- }
- }
- }
- return $errors;
-}
-
-/**
- * Determine rule hierarchy
- *
- * @param array $rules array of rules.
- * @return string
- */
-function edac_deteremine_hierarchy( $rules ) {
- $first = '';
- $rules = array_reverse( $rules );
-
- foreach ( $rules as $key => $value ) {
- if ( ( 'background' === $key || 'background-color' === $key ) && '' !== $value ) {
- $first = $key;
- break;
- }
- }
-
- // if background color has preference and is marked important then return background color.
- if ( 'background-color' === $first && stristr( $rules['background-color'], '!important' ) ) {
- return 'background-color';
- }
-
- // if background has preference and is not marked important but background color is then return background color.
- if (
- 'background' === $first && ! stristr( $rules['background'], '!important' )
- && ( array_key_exists( 'background-color', $rules ) && stristr( $rules['background-color'], '!important' ) )
- ) {
- return 'background-color';
- }
-
- // if background color has preference but is not marked important but background is and has a color value then return background.
- if (
- 'background-color' === $first && ! stristr( $rules['background-color'], '!important' )
- && ( array_key_exists( 'background', $rules )
- && stristr( $rules['background'], '!important' )
- && edac_check_color_match2( $rules['background'] ) )
- ) {
- return 'background';
- }
-
- if ( 'background' === $first && edac_check_color_match2( $rules['background'] ) ) {
- return 'background';
- }
- if ( array_key_exists( 'background-color', $rules ) ) {
- return 'background-color';
- }
-
- return $first;
-}
-
-/**
- * Check the color contrast
- *
- * @param string $foreground color hex.
- * @param string $background color hex.
- * @param int $ratio number.
- * @return bool
- */
-function edac_coldiff( $foreground, $background, $ratio ) {
-
- // convert color names to hex.
- $foreground = trim( edac_convert_color_names( $foreground ) );
- $background = trim( edac_convert_color_names( $background ) );
-
- // convert hex to rgb.
- $color1 = edac_hex_to_rgb( $foreground );
- $color2 = edac_hex_to_rgb( $background );
-
- $dif = edac_test_color_diff( $color1, $color2 );
-
- // failed.
- if ( $dif < $ratio ) {
- if ( $dif < $ratio ) {
- return 1;
- }
- }
-
- return 0;
-}
-
-/**
- * Test color contrast
- *
- * @param array $color1 rgb color.
- * @param array $color2 rgb color.
- * @return int
- */
-function edac_test_color_diff( $color1, $color2 ) {
- $l1 = 0.2126 * pow( $color1['r'] / 255, 2.2 ) +
- 0.7152 * pow( $color1['g'] / 255, 2.2 ) +
- 0.0722 * pow( $color1['b'] / 255, 2.2 );
-
- $l2 = 0.2126 * pow( $color2['r'] / 255, 2.2 ) +
- 0.7152 * pow( $color2['g'] / 255, 2.2 ) +
- 0.0722 * pow( $color2['b'] / 255, 2.2 );
-
- return ( $l1 > $l2 )
- ? ( ( $l1 + 0.05 ) / ( $l2 + 0.05 ) ) + 0.05
- : ( ( $l2 + 0.05 ) / ( $l1 + 0.05 ) ) + 0.05;
-}
-
-/**
- * Convert hex to rgb
- *
- * @param string $hex code.
- * @param boolean $alpha is alpha or not.
- * @return string
- */
-function edac_hex_to_rgb( $hex, $alpha = false ) {
- $hex = str_replace( '#', '', $hex );
- $length = strlen( $hex );
- $rgb['r'] = hexdec( 6 === $length ? substr( $hex, 0, 2 ) : ( 3 === $length ? str_repeat( substr( $hex, 0, 1 ), 2 ) : 0 ) );
- $rgb['g'] = hexdec( 6 === $length ? substr( $hex, 2, 2 ) : ( 3 === $length ? str_repeat( substr( $hex, 1, 1 ), 2 ) : 0 ) );
- $rgb['b'] = hexdec( 6 === $length ? substr( $hex, 4, 2 ) : ( 3 === $length ? str_repeat( substr( $hex, 2, 1 ), 2 ) : 0 ) );
- if ( $alpha ) {
- $rgb['a'] = $alpha;
- }
- return $rgb;
-}
-
-/**
- * Convert color names to hex
- *
- * @param string $color_name string of color name.
- * @return string
- */
-function edac_convert_color_names( $color_name ) {
-
- if ( stristr( $color_name, 'rgb(' ) ) {
- $color_name = str_replace( 'rgb(', '', $color_name );
- $color_name = str_replace( ')', '', $color_name );
- $rgb = explode( ',', $color_name );
- return '#' . sprintf( '%02x', $rgb['0'] ) . sprintf( '%02x', $rgb['1'] ) . sprintf( '%02x', $rgb['2'] );
- }
-
- // standard 147 HTML color names.
- $colors = [
- 'aliceblue' => 'F0F8FF',
- 'antiquewhite' => 'FAEBD7',
- 'aqua' => '00FFFF',
- 'aquamarine' => '7FFFD4',
- 'azure' => 'F0FFFF',
- 'beige' => 'F5F5DC',
- 'bisque' => 'FFE4C4',
- 'black' => '000000',
- 'blanchedalmond ' => 'FFEBCD',
- 'blue' => '0000FF',
- 'blueviolet' => '8A2BE2',
- 'brown' => 'A52A2A',
- 'burlywood' => 'DEB887',
- 'cadetblue' => '5F9EA0',
- 'chartreuse' => '7FFF00',
- 'chocolate' => 'D2691E',
- 'coral' => 'FF7F50',
- 'cornflowerblue' => '6495ED',
- 'cornsilk' => 'FFF8DC',
- 'crimson' => 'DC143C',
- 'cyan' => '00FFFF',
- 'darkblue' => '00008B',
- 'darkcyan' => '008B8B',
- 'darkgoldenrod' => 'B8860B',
- 'darkgray' => 'A9A9A9',
- 'darkgreen' => '006400',
- 'darkgrey' => 'A9A9A9',
- 'darkkhaki' => 'BDB76B',
- 'darkmagenta' => '8B008B',
- 'darkolivegreen' => '556B2F',
- 'darkorange' => 'FF8C00',
- 'darkorchid' => '9932CC',
- 'darkred' => '8B0000',
- 'darksalmon' => 'E9967A',
- 'darkseagreen' => '8FBC8F',
- 'darkslateblue' => '483D8B',
- 'darkslategray' => '2F4F4F',
- 'darkslategrey' => '2F4F4F',
- 'darkturquoise' => '00CED1',
- 'darkviolet' => '9400D3',
- 'deeppink' => 'FF1493',
- 'deepskyblue' => '00BFFF',
- 'dimgray' => '696969',
- 'dimgrey' => '696969',
- 'dodgerblue' => '1E90FF',
- 'firebrick' => 'B22222',
- 'floralwhite' => 'FFFAF0',
- 'forestgreen' => '228B22',
- 'fuchsia' => 'FF00FF',
- 'gainsboro' => 'DCDCDC',
- 'ghostwhite' => 'F8F8FF',
- 'gold' => 'FFD700',
- 'goldenrod' => 'DAA520',
- 'gray' => '808080',
- 'green' => '008000',
- 'greenyellow' => 'ADFF2F',
- 'grey' => '808080',
- 'honeydew' => 'F0FFF0',
- 'hotpink' => 'FF69B4',
- 'indianred' => 'CD5C5C',
- 'indigo' => '4B0082',
- 'ivory' => 'FFFFF0',
- 'khaki' => 'F0E68C',
- 'lavender' => 'E6E6FA',
- 'lavenderblush' => 'FFF0F5',
- 'lawngreen' => '7CFC00',
- 'lemonchiffon' => 'FFFACD',
- 'lightblue' => 'ADD8E6',
- 'lightcoral' => 'F08080',
- 'lightcyan' => 'E0FFFF',
- 'lightgoldenrodyellow' => 'FAFAD2',
- 'lightgray' => 'D3D3D3',
- 'lightgreen' => '90EE90',
- 'lightgrey' => 'D3D3D3',
- 'lightpink' => 'FFB6C1',
- 'lightsalmon' => 'FFA07A',
- 'lightseagreen' => '20B2AA',
- 'lightskyblue' => '87CEFA',
- 'lightslategray' => '778899',
- 'lightslategrey' => '778899',
- 'lightsteelblue' => 'B0C4DE',
- 'lightyellow' => 'FFFFE0',
- 'lime' => '00FF00',
- 'limegreen' => '32CD32',
- 'linen' => 'FAF0E6',
- 'magenta' => 'FF00FF',
- 'maroon' => '800000',
- 'mediumaquamarine' => '66CDAA',
- 'mediumblue' => '0000CD',
- 'mediumorchid' => 'BA55D3',
- 'mediumpurple' => '9370D0',
- 'mediumseagreen' => '3CB371',
- 'mediumslateblue' => '7B68EE',
- 'mediumspringgreen' => '00FA9A',
- 'mediumturquoise' => '48D1CC',
- 'mediumvioletred' => 'C71585',
- 'midnightblue' => '191970',
- 'mintcream' => 'F5FFFA',
- 'mistyrose' => 'FFE4E1',
- 'moccasin' => 'FFE4B5',
- 'navajowhite' => 'FFDEAD',
- 'navy' => '000080',
- 'oldlace' => 'FDF5E6',
- 'olive' => '808000',
- 'olivedrab' => '6B8E23',
- 'orange' => 'FFA500',
- 'orangered' => 'FF4500',
- 'orchid' => 'DA70D6',
- 'palegoldenrod' => 'EEE8AA',
- 'palegreen' => '98FB98',
- 'paleturquoise' => 'AFEEEE',
- 'palevioletred' => 'DB7093',
- 'papayawhip' => 'FFEFD5',
- 'peachpuff' => 'FFDAB9',
- 'peru' => 'CD853F',
- 'pink' => 'FFC0CB',
- 'plum' => 'DDA0DD',
- 'powderblue' => 'B0E0E6',
- 'purple' => '800080',
- 'red' => 'FF0000',
- 'rosybrown' => 'BC8F8F',
- 'royalblue' => '4169E1',
- 'saddlebrown' => '8B4513',
- 'salmon' => 'FA8072',
- 'sandybrown' => 'F4A460',
- 'seagreen' => '2E8B57',
- 'seashell' => 'FFF5EE',
- 'sienna' => 'A0522D',
- 'silver' => 'C0C0C0',
- 'skyblue' => '87CEEB',
- 'slateblue' => '6A5ACD',
- 'slategray' => '708090',
- 'slategrey' => '708090',
- 'snow' => 'FFFAFA',
- 'springgreen' => '00FF7F',
- 'steelblue' => '4682B4',
- 'tan' => 'D2B48C',
- 'teal' => '008080',
- 'thistle' => 'D8BFD8',
- 'tomato' => 'FF6347',
- 'turquoise' => '40E0D0',
- 'violet' => 'EE82EE',
- 'wheat' => 'F5DEB3',
- 'white' => 'FFFFFF',
- 'whitesmoke' => 'F5F5F5',
- 'yellow' => 'FFFF00',
- 'yellowgreen' => '9ACD32',
- ];
-
- $color_name = strtolower( $color_name );
- $color_name = trim( str_replace( '!important', '', $color_name ) );
-
- if ( isset( $colors[ $color_name ] ) ) {
- return ( '#' . $colors[ $color_name ] );
- }
- return ( $color_name );
-}
-
-/**
- * Check background style for color
- *
- * @param string $background_rule string of background.
- * @return string
- */
-function edac_check_color_match2( $background_rule ) {
-
- // standard 147 HTML color names.
- $colors = [
- 'aliceblue' => 'F0F8FF',
- 'antiquewhite' => 'FAEBD7',
- 'aqua' => '00FFFF',
- 'aquamarine' => '7FFFD4',
- 'azure' => 'F0FFFF',
- 'beige' => 'F5F5DC',
- 'bisque' => 'FFE4C4',
- 'black' => '000000',
- 'blanchedalmond ' => 'FFEBCD',
- 'blue' => '0000FF',
- 'blueviolet' => '8A2BE2',
- 'brown' => 'A52A2A',
- 'burlywood' => 'DEB887',
- 'cadetblue' => '5F9EA0',
- 'chartreuse' => '7FFF00',
- 'chocolate' => 'D2691E',
- 'coral' => 'FF7F50',
- 'cornflowerblue' => '6495ED',
- 'cornsilk' => 'FFF8DC',
- 'crimson' => 'DC143C',
- 'cyan' => '00FFFF',
- 'darkblue' => '00008B',
- 'darkcyan' => '008B8B',
- 'darkgoldenrod' => 'B8860B',
- 'darkgray' => 'A9A9A9',
- 'darkgreen' => '006400',
- 'darkgrey' => 'A9A9A9',
- 'darkkhaki' => 'BDB76B',
- 'darkmagenta' => '8B008B',
- 'darkolivegreen' => '556B2F',
- 'darkorange' => 'FF8C00',
- 'darkorchid' => '9932CC',
- 'darkred' => '8B0000',
- 'darksalmon' => 'E9967A',
- 'darkseagreen' => '8FBC8F',
- 'darkslateblue' => '483D8B',
- 'darkslategray' => '2F4F4F',
- 'darkslategrey' => '2F4F4F',
- 'darkturquoise' => '00CED1',
- 'darkviolet' => '9400D3',
- 'deeppink' => 'FF1493',
- 'deepskyblue' => '00BFFF',
- 'dimgray' => '696969',
- 'dimgrey' => '696969',
- 'dodgerblue' => '1E90FF',
- 'firebrick' => 'B22222',
- 'floralwhite' => 'FFFAF0',
- 'forestgreen' => '228B22',
- 'fuchsia' => 'FF00FF',
- 'gainsboro' => 'DCDCDC',
- 'ghostwhite' => 'F8F8FF',
- 'gold' => 'FFD700',
- 'goldenrod' => 'DAA520',
- 'gray' => '808080',
- 'green' => '008000',
- 'greenyellow' => 'ADFF2F',
- 'grey' => '808080',
- 'honeydew' => 'F0FFF0',
- 'hotpink' => 'FF69B4',
- 'indianred' => 'CD5C5C',
- 'indigo' => '4B0082',
- 'ivory' => 'FFFFF0',
- 'khaki' => 'F0E68C',
- 'lavender' => 'E6E6FA',
- 'lavenderblush' => 'FFF0F5',
- 'lawngreen' => '7CFC00',
- 'lemonchiffon' => 'FFFACD',
- 'lightblue' => 'ADD8E6',
- 'lightcoral' => 'F08080',
- 'lightcyan' => 'E0FFFF',
- 'lightgoldenrodyellow' => 'FAFAD2',
- 'lightgray' => 'D3D3D3',
- 'lightgreen' => '90EE90',
- 'lightgrey' => 'D3D3D3',
- 'lightpink' => 'FFB6C1',
- 'lightsalmon' => 'FFA07A',
- 'lightseagreen' => '20B2AA',
- 'lightskyblue' => '87CEFA',
- 'lightslategray' => '778899',
- 'lightslategrey' => '778899',
- 'lightsteelblue' => 'B0C4DE',
- 'lightyellow' => 'FFFFE0',
- 'lime' => '00FF00',
- 'limegreen' => '32CD32',
- 'linen' => 'FAF0E6',
- 'magenta' => 'FF00FF',
- 'maroon' => '800000',
- 'mediumaquamarine' => '66CDAA',
- 'mediumblue' => '0000CD',
- 'mediumorchid' => 'BA55D3',
- 'mediumpurple' => '9370D0',
- 'mediumseagreen' => '3CB371',
- 'mediumslateblue' => '7B68EE',
- 'mediumspringgreen' => '00FA9A',
- 'mediumturquoise' => '48D1CC',
- 'mediumvioletred' => 'C71585',
- 'midnightblue' => '191970',
- 'mintcream' => 'F5FFFA',
- 'mistyrose' => 'FFE4E1',
- 'moccasin' => 'FFE4B5',
- 'navajowhite' => 'FFDEAD',
- 'navy' => '000080',
- 'oldlace' => 'FDF5E6',
- 'olive' => '808000',
- 'olivedrab' => '6B8E23',
- 'orange' => 'FFA500',
- 'orangered' => 'FF4500',
- 'orchid' => 'DA70D6',
- 'palegoldenrod' => 'EEE8AA',
- 'palegreen' => '98FB98',
- 'paleturquoise' => 'AFEEEE',
- 'palevioletred' => 'DB7093',
- 'papayawhip' => 'FFEFD5',
- 'peachpuff' => 'FFDAB9',
- 'peru' => 'CD853F',
- 'pink' => 'FFC0CB',
- 'plum' => 'DDA0DD',
- 'powderblue' => 'B0E0E6',
- 'purple' => '800080',
- 'red' => 'FF0000',
- 'rosybrown' => 'BC8F8F',
- 'royalblue' => '4169E1',
- 'saddlebrown' => '8B4513',
- 'salmon' => 'FA8072',
- 'sandybrown' => 'F4A460',
- 'seagreen' => '2E8B57',
- 'seashell' => 'FFF5EE',
- 'sienna' => 'A0522D',
- 'silver' => 'C0C0C0',
- 'skyblue' => '87CEEB',
- 'slateblue' => '6A5ACD',
- 'slategray' => '708090',
- 'slategrey' => '708090',
- 'snow' => 'FFFAFA',
- 'springgreen' => '00FF7F',
- 'steelblue' => '4682B4',
- 'tan' => 'D2B48C',
- 'teal' => '008080',
- 'thistle' => 'D8BFD8',
- 'tomato' => 'FF6347',
- 'turquoise' => '40E0D0',
- 'violet' => 'EE82EE',
- 'wheat' => 'F5DEB3',
- 'white' => 'FFFFFF',
- 'whitesmoke' => 'F5F5F5',
- 'yellow' => 'FFFF00',
- 'yellowgreen' => '9ACD32',
- ];
-
- $background_rule = strtolower( $background_rule );
- $background_rule = trim( str_replace( '!important', '', $background_rule ) );
-
- $rules = explode( ' ', $background_rule );
-
- foreach ( $rules as $rule ) {
-
- if ( array_key_exists( $rule, $colors ) ) {
- return $colors[ $rule ];
- }
-
- if ( preg_match( '/(rgb\(\s*\d{1,3},\s*\d{1,3},\s*\d{1,3}\)|\#[\w]{3,6})/i', $rule, $matches, PREG_OFFSET_CAPTURE ) ) {
- return $matches[1][0];
- }
- }
- return '';
-}
diff --git a/includes/validate.php b/includes/validate.php
index 8e08068a..78dd12be 100644
--- a/includes/validate.php
+++ b/includes/validate.php
@@ -115,10 +115,28 @@ function edac_validate( $post_ID, $post, $action ) {
return;
}
+ /**
+ * Allows to hook in before the validation process starts for a post.
+ *
+ * @since 1.4.0
+ *
+ * @param int $post_ID The ID of the post being saved.
+ * @param string $action The action being performed.
+ */
do_action( 'edac_before_validate', $post_ID, $action );
// apply filters to content.
$content = edac_get_content( $post );
+
+ /**
+ * Allows to hook in after the content has been retrieved for a post.
+ *
+ * @since 1.4.0
+ *
+ * @param int $post_ID The ID of the post being saved.
+ * @param array $content The content being retrieved.
+ * @param string $action The action being performed.
+ */
do_action( 'edac_after_get_content', $post_ID, $content, $action );
if ( ! $content['html'] ) {
@@ -145,6 +163,15 @@ function edac_validate( $post_ID, $post, $action ) {
if ( ( array_key_exists( 'ruleset', $rule ) && 'php' === $rule['ruleset'] ) ||
( ! array_key_exists( 'ruleset', $rule ) && $rule['slug'] )
) {
+ /**
+ * Allows to hook in before the rule has been run on the content.
+ *
+ * @since 1.4.0
+ *
+ * @param int $post_ID The ID of the post being saved.
+ * @param array $rule The rule being validated against the content.
+ * @param string $action The action being performed.
+ */
do_action( 'edac_before_rule', $post_ID, $rule, $action );
if ( EDAC_DEBUG === true ) {
$rule_process_time = microtime( true );
@@ -152,6 +179,16 @@ function edac_validate( $post_ID, $post, $action ) {
$errors = call_user_func( 'edac_rule_' . $rule['slug'], $content, $post );
if ( $errors && is_array( $errors ) ) {
+ /**
+ * Allows to hook in after the rule has been and get the errors list.
+ *
+ * @since 1.4.0
+ *
+ * @param int $post_ID The ID of the post being saved.
+ * @param array $rule The rule being validated against the content.
+ * @param array $errors The errors list generated by this rule from the content.
+ * @param string $action The action being performed.
+ */
do_action( 'edac_rule_errors', $post_ID, $rule, $errors, $action );
foreach ( $errors as $error ) {
( new Insert_Rule_Data() )->insert( $post, $rule['slug'], $rule['rule_type'], $object = $error );
@@ -161,6 +198,16 @@ function edac_validate( $post_ID, $post, $action ) {
$time_elapsed_secs = microtime( true ) - $rule_process_time;
$rule_performance_results[ $rule['slug'] ] = $time_elapsed_secs;
}
+
+ /**
+ * Allows to hook in after the rule has been run on the content.
+ *
+ * @since 1.4.0
+ *
+ * @param int $post_ID The ID of the post being saved.
+ * @param array $rule The rule being validated against the content.
+ * @param string $action The action being performed.
+ */
do_action( 'edac_after_rule', $post_ID, $rule, $action );
}
}
@@ -179,6 +226,14 @@ function edac_validate( $post_ID, $post, $action ) {
// set post meta checked.
update_post_meta( $post_ID, '_edac_post_checked', true );
+ /**
+ * Allows to hook in after the validation process has completed for a post.
+ *
+ * @since 1.4.0
+ *
+ * @param int $post_ID The ID of the post being saved.
+ * @param string $action The action being performed.
+ */
do_action( 'edac_after_validate', $post_ID, $action );
}
@@ -292,9 +347,10 @@ function edac_get_content( $post ) {
*
* For site security it is not recommended to use this filter in production.
*
- * @param bool $no_verify_ssl The boolean to check.
+ * @since 1.4.0
+ *
+ * @param bool $no_verify_ssl True if verify SSL should be disabled (as it must be in loopback connections), false if not.
*/
-
$no_verify_ssl = apply_filters( 'edac_no_verify_ssl', $is_local_loopback );
if ( $no_verify_ssl ) {
diff --git a/package.json b/package.json
index 10daa09e..5e1bee1f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "accessibility-checker",
- "version": "1.11.2",
+ "version": "1.12.0",
"description": "Audit and check your website for accessibility before you hit publish. In-post accessibility scanner and guidance.",
"author": "Equalize Digital",
"license": "GPL-2.0+",
diff --git a/partials/custom-meta-box.php b/partials/custom-meta-box.php
index 3bf7b5b8..f7cc0a49 100644
--- a/partials/custom-meta-box.php
+++ b/partials/custom-meta-box.php
@@ -7,13 +7,58 @@
?>
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
diff --git a/partials/settings-page.php b/partials/settings-page.php
index 28749166..0e83afc9 100644
--- a/partials/settings-page.php
+++ b/partials/settings-page.php
@@ -5,7 +5,13 @@
* @package Accessibility_Checker
*/
-// set up tab items and filter them.
+/**
+ * Filter the settings tab items.
+ *
+ * @since 1.4.0
+ *
+ * @param array $settings_tab_items The settings tab items as an array of arrays. Needs a 'slug', 'label', and 'order'.
+ */
$settings_tab_items = apply_filters(
'edac_filter_settings_tab_items',
[
@@ -88,7 +94,19 @@ function ( $a, $b ) {
-
+
diff --git a/readme.txt b/readme.txt
index e132babd..46147899 100644
--- a/readme.txt
+++ b/readme.txt
@@ -2,8 +2,8 @@
Contributors: equalizedigital, alh0319, stevejonesdev
Tags: accessibility, accessible, wcag, ada, WP accessibility
Requires at least: 6.2
-Tested up to: 6.5.2
-Stable tag: 1.11.2
+Tested up to: 6.5.3
+Stable tag: 1.12.0
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -171,6 +171,11 @@ No, Accessibility Checker runs completely on your server and does not require yo
== Changelog ==
+= 1.12.0 =
+* Fixed: Use the last generation time in summary widgets rather than last completed scan time
+* Improved: More accessible panels in the editor
+* Improved: Filter and action docs added/improved
+
= 1.11.2
* Fixed: Avoid displaying `0th` for readability score
* Removed: Some custom WP Playground detection code
@@ -208,39 +213,5 @@ No, Accessibility Checker runs completely on your server and does not require yo
* Created: Class to handle data purging and cleanup
* Deprecated: `edac_delete_post`, `edac_delete_post_meta`, `edac_delete_cpt_posts` functions
-= 1.9.3 =
-* Updated: capability checks for the welcome page, dashboard widget, and admin notices
-
-= 1.9.2 =
-* Fixed: filtered rules are not passed to the frontend highlighter, avoiding 'null' state issues
-* Updated: frontend highlighter buttons to be disabled until issues are confirmed
-* Updated: frontend highlighter buttons to show only after we know there are issues to display
-* Updated: frontend highlighter to not show buttons if none are returned
-
-= 1.9.1 =
-* Updated: `edac_include_rules_files to fire on init action to fix the `edac_filter_register_rules` filter timing
-
-= 1.9.0 =
-* Created: class that creates the accessibility statement on activation
-* Removed: custom database query that checked for existing accessibility statement in exchange for the `get_page_by_path()` function
-* Fixed: bug with trying to compare the simplified summary ordinal value and added fallback
-* Removed: `wp_send_json_error()` from `simplified_summary` Ajax function when the simplified summary is empty
-* Added: simplified summary grade*level, message, and icon logic to the `summary()` Ajax
-* Fixed: issue with the submit button text showing as `Submit Query` in Firefox.
-* Updated: missing transcript rule to skip certain types of links
-* Added: missing UTM parameters to the welcome page URLs.
-* Removed: legacy system information code
-* Removed: cbschuld/browser.php composer package
-* Added: class structure for site health
-* Added: site health health information for free, pro, and audit history plugins
-* Added: update database class
-* Removed: `edac_before_page_render` functions from the main file
-* Added: frontend validate class
-* Added: frontend validate unit tests
-* Removed: unused new window warning meta update functions
-* Fixed: front end highlight focus issue
-* Added: summary generator class to replace the `edac_summary()` function
-* Deprecated: `edac_summary()` function
-
Older versions can be found in the plugins `changelog.txt`.
diff --git a/src/admin/index.js b/src/admin/index.js
index fef24af0..14cba42a 100644
--- a/src/admin/index.js
+++ b/src/admin/index.js
@@ -1,5 +1,10 @@
/* eslint-disable no-unused-vars */
+import {
+ clearAllTabsAndPanelState,
+ initSummaryTabKeyboardAndClickHandlers,
+} from './summary/summary-tab-input-event-handlers';
+
// eslint-disable-next-line camelcase
const edacScriptVars = edac_script_vars;
@@ -47,15 +52,20 @@ const edacScriptVars = edac_script_vars;
} );
jQuery( window ).on( 'load', function() {
- // Allow other js to trigger a tab refresh thru an event listener. Refactor.
+ // Allow other js to trigger a tab refresh through an event listener. Refactor.
const refreshTabDetails = () => {
// reset to first meta box tab
- jQuery( '.edac-panel' ).hide();
- jQuery( '.edac-panel' ).removeClass( 'active' );
- jQuery( '.edac-tab a' ).removeClass( 'active' );
- jQuery( '#edac-summary' ).show();
- jQuery( '#edac-summary' ).addClass( 'active' );
- jQuery( '.edac-tab:first-child a' ).addClass( 'active' );
+ clearAllTabsAndPanelState();
+
+ const summaryPanel = jQuery( '#edac-summary-panel' );
+ jQuery( summaryPanel )
+ .show()
+ .addClass( 'active' );
+ const summaryTab = '#' + jQuery( summaryPanel ).attr( 'aria-labelledby' );
+ jQuery( summaryTab )
+ .addClass( 'active' )
+ .attr( 'aria-selected', 'true' )
+ .removeAttr( 'tabindex' );
edacDetailsAjax();
refreshSummaryAndReadability();
@@ -76,30 +86,6 @@ const edacScriptVars = edac_script_vars;
} );
};
- jQuery( '.edac-tab' ).click( function( e ) {
- e.preventDefault();
- const id = jQuery( 'a', this ).attr( 'href' );
-
- jQuery( '.edac-panel' ).hide();
- jQuery( '.edac-panel' ).removeClass( 'active' );
- jQuery( '.edac-tab a' )
- .removeClass( 'active' )
- .attr( 'aria-current', false );
- jQuery( id ).show();
- jQuery( id ).addClass( 'active' );
- jQuery( 'a', this ).addClass( 'active' ).attr( 'aria-current', true );
- } );
-
- // Details Tab on click Ajax
- jQuery( '.edac-tab-details' ).click( function() {
- edacDetailsAjax();
- } );
-
- // Summary Tab on click Ajax
- jQuery( '.edac-tab-summary' ).click( function() {
- refreshSummaryAndReadability();
- } );
-
/**
* Ajax Summary
* @param {Function} callback - Callback function to run after ajax is complete
@@ -157,7 +143,7 @@ const edacScriptVars = edac_script_vars;
if ( true === response.success ) {
const responseJSON = jQuery.parseJSON( response.data );
- jQuery( '.edac-details' ).html( responseJSON );
+ jQuery( '#edac-details-panel' ).html( responseJSON );
// Rule on click
jQuery( '.edac-details-rule-title' ).click( function() {
@@ -232,7 +218,7 @@ const edacScriptVars = edac_script_vars;
if ( true === response.success ) {
const responseJSON = jQuery.parseJSON( response.data );
- jQuery( '.edac-readability' ).html( responseJSON );
+ jQuery( '#edac-readability-panel' ).html( responseJSON );
// Simplified Summary on click
jQuery( '.edac-readability-simplified-summary' ).submit(
@@ -580,17 +566,16 @@ const edacScriptVars = edac_script_vars;
} );
}
- if ( jQuery( '.edac-summary' ).length ) {
+ if ( jQuery( '#edac-summary-panel' ).length ) {
refreshSummaryAndReadability();
- }
- if ( jQuery( '.edac-details' ).length ) {
edacDetailsAjax();
ignoreSubmit();
}
+
if ( jQuery( '.edac-details-rule-records-record-ignore' ).length ) {
ignoreSubmit();
}
- if ( jQuery( '.edac-readability' ).length ) {
+ if ( jQuery( '#edac-readability-panel' ).length ) {
refreshSummaryAndReadability();
}
@@ -644,6 +629,11 @@ const edacScriptVars = edac_script_vars;
}( jQuery ) );
window.addEventListener( 'load', function() {
+ if ( document.getElementById( 'edac-tabs' ) ) {
+ // bind events for the summary metabox tabs and panels.
+ initSummaryTabKeyboardAndClickHandlers();
+ }
+
if ( this.document.querySelector( '.edac-widget .edac-summary' ) ) {
fillDashboardWidget();
}
@@ -709,26 +699,10 @@ const fillDashboardWidget = () => {
passedPercentageFormatted;
}
- // Set completedAt
- const completedAt = data.stats.fullscan_completed_at;
- const completedAtFormatted =
- data.stats.fullscan_completed_at_formatted;
- const completedAtEl = document.querySelector(
- '#edac-summary-info-date'
- );
- completedAtEl.textContent = completedAtFormatted;
-
- /*
- const expires_at = data.stats.expires_at;
- const now = Date.now();
- const mins_to_exp = Math.round((expires_at - Math.floor(now / 1000))/60);
- const cache_hit = data.stats.cache_hit;
- if(completedAtEl && completedAt){
- completedAtEl.textContent = completedAt;
- completedAtEl.setAttribute('data-edac-cache-hit', cache_hit);
- completedAtEl.setAttribute('data-edac-cache-mins-to-expiration', mins_to_exp + ' minutes');
- }
- */
+ // Set the summary cached at time for display in the dashboard widget.
+ const summaryCachedAt = data.stats.cached_at_formatted || data.stats.fullscan_completed_at_formatted;
+ const summaryCachedAtEl = document.getElementById( 'edac-summary-info-date' );
+ summaryCachedAtEl.textContent = summaryCachedAt;
// scanned
const postsScanned = data.stats.posts_scanned;
diff --git a/src/admin/sass/accessibility-checker-admin.scss b/src/admin/sass/accessibility-checker-admin.scss
index 5a9cbabd..879092c0 100644
--- a/src/admin/sass/accessibility-checker-admin.scss
+++ b/src/admin/sass/accessibility-checker-admin.scss
@@ -63,6 +63,8 @@
.edac-tabs {
margin-bottom: 0;
+ position: relative;
+ z-index: 2;
}
.edac-tab {
@@ -70,7 +72,7 @@
margin-bottom: 0;
vertical-align: bottom;
- a {
+ > button {
width: 100%;
padding: 12px 18px;
display: inline-block;
@@ -79,14 +81,27 @@
border-bottom: none;
text-decoration: none;
font-size: 14px;
+ color: $color-blue;
@include breakpoint(xs) {
width: auto;
}
+ &:hover,
+ &:focus {
+ color: $color-black;
+ cursor: pointer;
+ }
+
+ &:focus-visible {
+ outline: 2px solid $color-blue;
+ outline-offset: 2px;
+ }
+
&.active {
padding: 14px 18px;
- background-color: $color-white;
+ color: $color-white;
+ background-color: $color-blue;
}
}
}
@@ -201,7 +216,7 @@
}
@include breakpoint(xl) {
- //transform: scale(1, 1);
+ //transform: scale(1, 1);
}
&:after {
@@ -1883,4 +1898,4 @@
z-index: 9;
}
-}
\ No newline at end of file
+}
diff --git a/src/admin/summary/summary-tab-input-event-handlers.js b/src/admin/summary/summary-tab-input-event-handlers.js
new file mode 100644
index 00000000..ac36f759
--- /dev/null
+++ b/src/admin/summary/summary-tab-input-event-handlers.js
@@ -0,0 +1,104 @@
+/**
+ * Summary Tab Input Event Handlers
+ *
+ * @since 1.12.0
+ */
+
+/**
+ * Initialize the Summary Tab keyboard and click event handlers.
+ *
+ * Gets all tabs, adds click and keydown event listeners to each tab to support
+ * proper keyboard navigation and aria attributes.
+ *
+ * @since 1.12.0
+ */
+export const initSummaryTabKeyboardAndClickHandlers = () => {
+ const tabs = document.querySelectorAll( '.edac-tab button' );
+
+ tabs.forEach( ( tab, index ) => {
+ tab.addEventListener( 'click', ( event ) => {
+ if (
+ ! ( event.target instanceof HTMLButtonElement ) &&
+ 'undefined' !== event.target.getAttribute( 'aria-controls' )
+ ) {
+ return;
+ }
+
+ const panel = document.querySelector( '#' + event.target.getAttribute( 'aria-controls' ) );
+ if ( ! ( panel instanceof HTMLElement ) ) {
+ return;
+ }
+
+ event.preventDefault();
+ clearAllTabsAndPanelState();
+
+ panel.style.display = 'block';
+ panel.classList.add( 'active' );
+ event.target.classList.add( 'active' );
+ event.target.setAttribute( 'aria-selected', true );
+ event.target.removeAttribute( 'tabindex' );
+ event.target.focus();
+ } );
+
+ // all the events that result in true evaluations simply click the tab in question,
+ // because the tab click handler is already setup and not worth currently fully refactoring.
+ tab.addEventListener( 'keydown', ( event ) => {
+ if (
+ ( event.key === 'Enter' || event.keyCode === 13 ) ||
+ ( event.key === 'Space' || event.keyCode === 32 )
+ ) {
+ tabs[ index ].click();
+ }
+
+ if ( event.key === 'ArrowRight' || event.keyCode === 39 ) {
+ let newTabIndex = index + 1;
+ if ( newTabIndex > tabs.length ) {
+ newTabIndex = 0;
+ }
+ tabs[ newTabIndex ].click();
+ }
+
+ if ( event.key === 'ArrowLeft' || event.keyCode === 37 ) {
+ let newTabIndex = index - 1;
+ if ( newTabIndex < 0 ) {
+ newTabIndex = tabs.length - 1;
+ }
+ tabs[ newTabIndex ].click();
+ }
+
+ if ( event.key === 'Home' || event.keyCode === 36 ) {
+ tabs[ 0 ].click();
+ event.preventDefault();
+ }
+
+ if ( event.key === 'End' || event.keyCode === 35 ) {
+ tabs[ tabs.length - 1 ].click();
+ event.preventDefault();
+ }
+ } );
+ } );
+};
+
+/**
+ * Clear all tabs and panels state to inactive then set a default active tab and panel.
+ *
+ * @since 1.12.0
+ */
+export const clearAllTabsAndPanelState = () => {
+ const panels = document.querySelectorAll( '.edac-panel' );
+ if ( ! panels.length ) {
+ return;
+ }
+
+ panels.forEach( ( panel ) => {
+ panel.style.display = 'none';
+ panel.classList.remove( 'active' );
+ panel.setAttribute( 'aria-selected', 'false' );
+ const panelTab = document.querySelector( '#' + panel.getAttribute( 'aria-labelledby' ) );
+ if ( panelTab ) {
+ panelTab.classList.remove( 'active' );
+ panelTab.setAttribute( 'aria-selected', 'false' );
+ panelTab.setAttribute( 'tabindex', '-1' );
+ }
+ } );
+};
diff --git a/tests/phpunit/Admin/MetaBoxesTest.php b/tests/phpunit/Admin/MetaBoxesTest.php
index 9feb4282..1c80f8e1 100644
--- a/tests/phpunit/Admin/MetaBoxesTest.php
+++ b/tests/phpunit/Admin/MetaBoxesTest.php
@@ -61,7 +61,10 @@ public function test_render(): void {
$meta_boxes = new Meta_Boxes();
$meta_boxes->render();
- $this->expectOutputRegex( '/^/' );
+ $this->expectOutputRegex( '/^
expectOutputRegex( '/role="tablist"/' );
+ $this->expectOutputRegex( '/role="tab"/' );
+ $this->expectOutputRegex( '/role="tabpanel"/' );
}
/**