From fef75dabee12c0db19570e8cfe380f24ec08a018 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 20:33:51 +0000 Subject: [PATCH 001/161] Bump braces from 3.0.2 to 3.0.3 in /accessibility-checker-extension Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../package-lock.json | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/accessibility-checker-extension/package-lock.json b/accessibility-checker-extension/package-lock.json index 8d7ebbf48..0df9327d8 100644 --- a/accessibility-checker-extension/package-lock.json +++ b/accessibility-checker-extension/package-lock.json @@ -4029,11 +4029,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -6451,9 +6451,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -15695,11 +15695,11 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browserslist": { @@ -17481,9 +17481,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "requires": { "to-regex-range": "^5.0.1" } From 407cce81d8003cd9065d6693c9e272734ded9965 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 2 Aug 2024 17:00:53 -0500 Subject: [PATCH 002/161] Starter project --- java-accessibility-checker/.gitattributes | 12 + java-accessibility-checker/.gitignore | 5 + .../gradle/libs.versions.toml | 12 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43504 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + java-accessibility-checker/gradlew | 252 ++++++++++++++++++ java-accessibility-checker/gradlew.bat | 94 +++++++ java-accessibility-checker/lib/build.gradle | 43 +++ .../src/main/java/org/example/Library.java | 10 + .../test/java/org/example/LibraryTest.java | 41 +++ java-accessibility-checker/settings.gradle | 14 + 11 files changed, 490 insertions(+) create mode 100644 java-accessibility-checker/.gitattributes create mode 100644 java-accessibility-checker/.gitignore create mode 100644 java-accessibility-checker/gradle/libs.versions.toml create mode 100644 java-accessibility-checker/gradle/wrapper/gradle-wrapper.jar create mode 100644 java-accessibility-checker/gradle/wrapper/gradle-wrapper.properties create mode 100755 java-accessibility-checker/gradlew create mode 100644 java-accessibility-checker/gradlew.bat create mode 100644 java-accessibility-checker/lib/build.gradle create mode 100644 java-accessibility-checker/lib/src/main/java/org/example/Library.java create mode 100644 java-accessibility-checker/lib/src/test/java/org/example/LibraryTest.java create mode 100644 java-accessibility-checker/settings.gradle diff --git a/java-accessibility-checker/.gitattributes b/java-accessibility-checker/.gitattributes new file mode 100644 index 000000000..f91f64602 --- /dev/null +++ b/java-accessibility-checker/.gitattributes @@ -0,0 +1,12 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + +# Binary files should be left untouched +*.jar binary + diff --git a/java-accessibility-checker/.gitignore b/java-accessibility-checker/.gitignore new file mode 100644 index 000000000..1b6985c00 --- /dev/null +++ b/java-accessibility-checker/.gitignore @@ -0,0 +1,5 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/java-accessibility-checker/gradle/libs.versions.toml b/java-accessibility-checker/gradle/libs.versions.toml new file mode 100644 index 000000000..ab0036d1b --- /dev/null +++ b/java-accessibility-checker/gradle/libs.versions.toml @@ -0,0 +1,12 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format + +[versions] +commons-math3 = "3.6.1" +guava = "33.1.0-jre" +junit = "4.13.2" + +[libraries] +commons-math3 = { module = "org.apache.commons:commons-math3", version.ref = "commons-math3" } +guava = { module = "com.google.guava:guava", version.ref = "guava" } +junit = { module = "junit:junit", version.ref = "junit" } diff --git a/java-accessibility-checker/gradle/wrapper/gradle-wrapper.jar b/java-accessibility-checker/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2c3521197d7c4586c843d1d3e9090525f1898cde GIT binary patch literal 43504 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 TZiJi*F`$tkWLn) literal 0 HcmV?d00001 diff --git a/java-accessibility-checker/gradle/wrapper/gradle-wrapper.properties b/java-accessibility-checker/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..09523c0e5 --- /dev/null +++ b/java-accessibility-checker/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/java-accessibility-checker/gradlew b/java-accessibility-checker/gradlew new file mode 100755 index 000000000..f5feea6d6 --- /dev/null +++ b/java-accessibility-checker/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/java-accessibility-checker/gradlew.bat b/java-accessibility-checker/gradlew.bat new file mode 100644 index 000000000..9d21a2183 --- /dev/null +++ b/java-accessibility-checker/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle new file mode 100644 index 000000000..024eb4aa3 --- /dev/null +++ b/java-accessibility-checker/lib/build.gradle @@ -0,0 +1,43 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.9/userguide/building_java_projects.html in the Gradle documentation. + */ + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'java-library' +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +dependencies { + // Use JUnit test framework. + testImplementation libs.junit + + // This dependency is exported to consumers, that is to say found on their compile classpath. + api libs.commons.math3 + + // This dependency is used internally, and not exposed to consumers on their own compile classpath. + implementation libs.guava + + // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java + implementation 'org.seleniumhq.selenium:selenium-java:4.16.1' +} + +// Apply a specific Java toolchain to ease working on different environments. +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +test { + testLogging { + showStandardStreams = true + } +} \ No newline at end of file diff --git a/java-accessibility-checker/lib/src/main/java/org/example/Library.java b/java-accessibility-checker/lib/src/main/java/org/example/Library.java new file mode 100644 index 000000000..b98461bb7 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/org/example/Library.java @@ -0,0 +1,10 @@ +/* + * This source file was generated by the Gradle 'init' task + */ +package org.example; + +public class Library { + public boolean someLibraryMethod() { + return true; + } +} diff --git a/java-accessibility-checker/lib/src/test/java/org/example/LibraryTest.java b/java-accessibility-checker/lib/src/test/java/org/example/LibraryTest.java new file mode 100644 index 000000000..834cbdfc2 --- /dev/null +++ b/java-accessibility-checker/lib/src/test/java/org/example/LibraryTest.java @@ -0,0 +1,41 @@ +/* + * This source file was generated by the Gradle 'init' task + */ +package org.example; + +import org.junit.Test; +import static org.junit.Assert.*; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +// import org.openqa.selenium.WebDriver; +import org.openqa.selenium.chrome.ChromeDriver; + +public class LibraryTest { + private static ChromeDriver driver; + + /** + * Setup a Selenium Chrome environment before tests + */ + @BeforeClass public static void setup() { + String workingDir = System.getProperty("user.dir"); + String chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; + System.setProperty("webdriver.chrome.driver", chromeDriverDir); + LibraryTest.driver = new ChromeDriver(); + } + + /** + * Close Selenium Chrome environment after tests + */ + @AfterClass public static void teardown() { + LibraryTest.driver.close(); + } + + @Test public void someLibraryMethodReturnsTrue() { + LibraryTest.driver.get("https://altoromutual.12mc9fdq8fib.us-south.codeengine.appdomain.cloud/"); + String pageTitle = driver.getTitle(); + System.out.println("Page Title: " + pageTitle); + Library classUnderTest = new Library(); + assertTrue("someLibraryMethod should return 'true'", classUnderTest.someLibraryMethod()); + } +} diff --git a/java-accessibility-checker/settings.gradle b/java-accessibility-checker/settings.gradle new file mode 100644 index 000000000..60a3ed8fe --- /dev/null +++ b/java-accessibility-checker/settings.gradle @@ -0,0 +1,14 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.9/userguide/multi_project_builds.html in the Gradle documentation. + */ + +plugins { + // Apply the foojay-resolver plugin to allow automatic download of JDKs + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' +} + +rootProject.name = 'java-accessibility-checker' +include('lib') From 72530487cfe504e156c3a635aa856a604678386a Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 2 Aug 2024 23:52:59 -0500 Subject: [PATCH 003/161] Basic config files --- .../example => com/ibm/able}/Library.java | 2 +- .../main/java/com/ibm/able/config/Config.java | 95 ++++++++++++++++++ .../com/ibm/able/config/ConfigInternal.java | 96 +++++++++++++++++++ .../example => com/ibm/able}/LibraryTest.java | 4 +- 4 files changed, 195 insertions(+), 2 deletions(-) rename java-accessibility-checker/lib/src/main/java/{org/example => com/ibm/able}/Library.java (87%) create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java rename java-accessibility-checker/lib/src/test/java/{org/example => com/ibm/able}/LibraryTest.java (96%) diff --git a/java-accessibility-checker/lib/src/main/java/org/example/Library.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/Library.java similarity index 87% rename from java-accessibility-checker/lib/src/main/java/org/example/Library.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/Library.java index b98461bb7..e1d609b90 100644 --- a/java-accessibility-checker/lib/src/main/java/org/example/Library.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/Library.java @@ -1,7 +1,7 @@ /* * This source file was generated by the Gradle 'init' task */ -package org.example; +package com.ibm.able; public class Library { public boolean someLibraryMethod() { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java new file mode 100644 index 000000000..9802f549a --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java @@ -0,0 +1,95 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.config; + +public class Config { + /** + * (optional) Specify the rule archive + * + * Run `npx achecker archives` for a list of valid ruleArchive ids and policy ids + * Default: "latest" + * Values: "latest" | "preview" | "versioned" | archive id + */ + public String ruleArchive = "latest"; + + /** + * (optional) Specify one or many policies to scan. + * + * Run `npx achecker archives` for a list of valid ruleArchive ids and policy ids + * Default: ["IBM_Accessibility"] + */ + public String[] policies = { "IBM_Accessibility" }; + + /** + * (optional) Specify one or many violation levels on which to fail the test + * + * i.e. If specified violation then the testcase will only fail if + * a violation is found during the scan. + * Default: ["violation", "review"] + */ + public String[] failLevels = { "violation", "potentialviolation" }; + + /** + * (optional) Specify one or many violation levels which should be reported + * + * i.e. If specified violation then in the report it would only contain + * results which are level of violation. + * Default: ["violation", "review"] + */ + public String[] reportLevels = { "violation", "potentialviolation" }; + + /** + * (optional) In which fornats should the results be output + * Default: ["json"] + */ + public String[] outputFormat = { "json" }; + + /** + * (optional) Specify any labels that you would like associated to your scan + * Default: [] + */ + public String[] label; + + /** + * (optional) Where the scan results should be saved. + * Default: "results" + */ + public String outputFolder; + + /** + * (optional) Should the timestamp be included in the filename of the reports? + * Default: true + */ + public boolean outputFilenameTimestamp = true; + + /** + * (optional) Where the baseline results should be loaded from + * Default: "baselines" + */ + public String baselineFolder = "baselines"; + + /** + * (optional) Where the tool can read/write cached files (ace-node.js / archive.json) + * Default: `${os.tmpdir()}/accessibility-checker/` + */ + public String cacheFolder = System.getProperty("java.io.tmpdir")+"/accessibility-checker/"; + + /** + * (optional) For tools that scan files, which extensions should we include + * Default: ["html", "htm", "svg"] + */ + public String[] extensions = { "html", "htm", "svg" }; +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java new file mode 100644 index 000000000..9f7a279d8 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java @@ -0,0 +1,96 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.config; + +import java.nio.file.Paths; + +public class ConfigInternal extends Config { + /** + * Run in debug mode + */ + public boolean DEBUG = "true".equals(System.getenv("DEBUG")); + + /** + * Spot to store parsed archive file + */ + // ruleArchiveSet?: IArchive[] + + /** + * Label to expose to reports + */ + public String ruleArchiveLabel; + + /** + * (optional) Rule server to pull the rules from and to use for help + * Default: "https://able.ibm.com/rules" + */ + public String ruleServer = "https://cdn.jsdelivr.net/npm/accessibility-checker-engine"; + + /** + * Path to the rule pack + */ + public String rulePack; + + /** + * Path within the archive + */ + public String ruleArchivePath; + + /** + * Version number of the selected archive + */ + public String ruleArchiveVersion; + + /** + * (optional) If the tool allows, should we capture screenshots + */ + public boolean captureScreenshots = false; + + /** + * (optional) If the tool allows, should we run headless + */ + public boolean headless = true; + + /** + * (optional) If the tool allows, set the maximum number of tabs to open + */ + public int maxTabs = 1; + + /** + * Configuration filenames to try loading + */ + public String[] configFiles = { + "achecker.json", + "aceconfig.json", + Paths.get(".config", "achecker.json").toString(), + Paths.get(".config", "aceconfig.json").toString() + }; + + public String toolID; + public String toolName; + public String toolVersion; + + public String scanID; + + public boolean ignoreHTTPSErrors = false; + + public boolean perfMetrics = true; + + /** + * "DEFAULT" | "REMOTE" | "INJECT" + */ + public String engineMode = "DEFAULT"; +} diff --git a/java-accessibility-checker/lib/src/test/java/org/example/LibraryTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java similarity index 96% rename from java-accessibility-checker/lib/src/test/java/org/example/LibraryTest.java rename to java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java index 834cbdfc2..48995cf39 100644 --- a/java-accessibility-checker/lib/src/test/java/org/example/LibraryTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java @@ -1,7 +1,7 @@ /* * This source file was generated by the Gradle 'init' task */ -package org.example; +package com.ibm.able; import org.junit.Test; import static org.junit.Assert.*; @@ -11,6 +11,8 @@ // import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; +import com.ibm.able.Library; + public class LibraryTest { private static ChromeDriver driver; From eb86a478277d73c5089d29334f56dab3fb2c3778 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 6 Aug 2024 11:12:58 -0500 Subject: [PATCH 004/161] Config starter --- java-accessibility-checker/lib/build.gradle | 1 + .../com/ibm/able/config/ACConfigManager.java | 375 ++++++++++++++++++ .../java/com/ibm/able/config/Archive.java | 39 ++ .../main/java/com/ibm/able/config/Config.java | 19 +- .../com/ibm/able/config/ConfigInternal.java | 28 +- .../main/java/com/ibm/able/util/Fetch.java | 64 +++ .../src/main/java/com/ibm/able/util/Misc.java | 28 ++ 7 files changed, 542 insertions(+), 12 deletions(-) create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Archive.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 024eb4aa3..990aeaf0b 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -27,6 +27,7 @@ dependencies { // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java implementation 'org.seleniumhq.selenium:selenium-java:4.16.1' + implementation 'com.google.code.gson:gson:2.11.0' } // Apply a specific Java toolchain to ease working on different environments. diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java new file mode 100644 index 000000000..86a969b53 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java @@ -0,0 +1,375 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ + +package com.ibm.able.config; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +import com.google.gson.Gson; +import com.google.gson.stream.JsonReader; +import com.ibm.able.config.Archive; +import com.ibm.able.util.Fetch; +import com.ibm.able.util.Misc; + +public class ACConfigManager { + private static class ConfigError extends Error { + ConfigError(String message) { + super(message); + } + + } + + private static String[] covertPolicies(String policies) { + return policies.split(","); + } + + + /** + * negative if versionA is less than versionB, positive if versionA is greater than versionB, and zero if they are equal. NaN is treated as 0. + * @param versionA + * @param versionB + */ + private static int compareVersions(String versionA, String versionB) { + Pattern versionRE = Pattern.compile("[0-9.]+(-rc.[0-9]+)?"); + versionA = versionA.trim(); + versionB = versionB.trim(); + if (!versionRE.matcher(versionA).matches()) throw new ConfigError("Invalid version"); + if (!versionRE.matcher(versionB).matches()) throw new ConfigError("Invalid version"); + if (versionA.equals(versionB)) return 0; + // Get x.y.z-rc.a into [x.y.z, a] + // Get x.y.z into [x.y.z] + String[] split1A = versionA.split("-rc."); + String[] split1B = versionB.split("-rc."); + // Get x.y.z into [x,y,z] + String[] split2A = split1A[0].split("."); + String[] split2B = split1B[0].split("."); + // For the components of the shortest version - can only compare numbers we have + int minLength = Math.min(split2A.length, split2B.length); + for (int idx=0; idx= 0) { + return archive.id; + } + } + // Something wrong, go with the latest + return "latest"; + } + + /** + * This function is responsible processing the achecker config which was initialized to make sure it contains, + * information which matches what the engine reads. + * + * i.e. + * Need to change reportLevels and failLevels to match with level declerations in the engine. + * replace violation with level.violation + * Need to change array of policies into a string + * ["CI162_5_2_DCP070116","CI162_5_2_DCP070116"] to "CI162_5_2_DCP070116,CI162_5_2_DCP070116" + * + * @param {Object} ACConfig - Provide the config object in which needs to be processed. + * + * @return {Object} ACConfig - return the config object which has been made engine readable + * + * @memberOf this + */ + private static ConfigInternal processACConfig(ConfigInternal ACConfig) throws IOException { + String[] validArchiveKeywords = { "latest", "preview", "versioned" }; + String ruleServer = ACConfig.ruleServer; + + // Get and parse the rule archive. + String ruleArchiveFile = String.format("%s%s/archives.json",ruleServer,ruleServer.contains("jsdelivr.net")?"@next":""); + Archive[] ruleArchiveParse; + try { + // if (ACConfig.ignoreHTTPSErrors) { + // process.env.NODE_TLS_REJECT_UNAUTHORIZED="0" + // } + ruleArchiveParse = Fetch.getJSONArr(ruleArchiveFile, Archive[].class); + } catch (Error err) { + System.err.println(err.toString()); + throw err; + } + String ruleArchivePath = null; + if (ruleArchiveParse.length > 0) { + if (ACConfig.DEBUG) System.out.println("Found archiveFile: " + ruleArchiveFile); + ACConfig.ruleArchiveSet = ruleArchiveParse; + String ruleArchive = ACConfig.ruleArchive; + // If the user asked us to sync the rule version with the tool version, we need to figure out what the last rule version was + if ("versioned".equals(ruleArchive)) { + if (ACConfig.toolVersion == null) { + ruleArchive = "latest"; + } else { + ruleArchive = findLatestArchiveId(ACConfig.ruleArchiveSet, ACConfig.toolVersion); + } + } + ACConfig.ruleArchiveLabel = ACConfig.ruleArchive; + for (int i = 0; i < ACConfig.ruleArchiveSet.length; i++) { + if (ruleArchive.equals(ACConfig.ruleArchiveSet[i].id) && !ACConfig.ruleArchiveSet[i].sunset) { + ruleArchivePath = ACConfig.ruleArchiveSet[i].path; + ACConfig.ruleArchiveVersion = ACConfig.ruleArchiveSet[i].version; + ACConfig.ruleArchiveLabel = ruleArchiveParse[i].name + " (" + ruleArchiveParse[i].id + ")"; + break; + } + } + if (ruleArchivePath == null || ACConfig.ruleArchiveVersion == null) { + String errStr = "[ERROR] RuleArchiveInvalid: Make Sure correct rule archive is provided in the configuration file. More information is available in the README.md"; + System.err.println(errStr); + throw new ConfigError(errStr); + } + for (int i = 0; i < ACConfig.ruleArchiveSet.length; i++) { + if (ACConfig.ruleArchiveVersion.equals(ACConfig.ruleArchiveSet[i].version) + && !Arrays.asList(validArchiveKeywords).contains(ACConfig.ruleArchiveSet[i].id)) + { + ACConfig.ruleArchivePath = ACConfig.ruleArchiveSet[i].path; + break; + } + } + //} + } else { + String errStr = "[ERROR] UnableToParseArchive: Archives are unable to be parse. Contact support team."; + System.err.println(errStr); + throw new ConfigError(errStr); + } + + // Build the new rulePack based of the baseA11yServerURL + if (ACConfig.rulePack == null || "".equals(ACConfig.rulePack)) { + if (ruleServer.contains("jsdelivr.net")) { + ACConfig.rulePack = String.format("%s@%s", ruleServer, ACConfig.ruleArchiveVersion); + } else { + ACConfig.rulePack = String.format("%s%s/js", ruleServer, ruleArchivePath); + } + } + ACConfig.ruleServer = ruleServer; + + if (ACConfig.DEBUG) System.err.println("Built new rulePack: " + ACConfig.rulePack); + + if (ACConfig.DEBUG) System.err.println("END 'processACConfig' function"); + + // Return the updated ACConfig object + return ACConfig; + } + + /** + * This function is responsible initializing all the default values for the configurations, in the case any + * of the config options are missing. + * + * @param {Object} config - Provide the config object in which we need to initialize the default values. + * + * @return {Object} config - return the config object which has all the default values, in the case + * some of the options are null or undefined. + * + * @memberOf this + */ + private static void initializeDefaults(ConfigInternal config) { + // Use an unpopulated config as the default values + ConfigInternal ACConstants = new ConfigInternal(); + if (config.DEBUG) System.out.println("START 'initializeDefaults' function"); + + if (config.DEBUG) System.out.println("Config before initialization: "); + if (config.DEBUG) System.out.println(config); + // Make sure all the following options are defined, otherwise reset them to default values. + config.ruleArchiveLabel = Misc.firstNotNull(config.ruleArchiveLabel, config.ruleArchive); + // For capture screenshots need to check for null or undefined and then set default otherwise it will evaluate the + // boolean which causes it to always comply with the default value and not user provided option + config.captureScreenshots = Misc.firstNotNull(config.captureScreenshots, ACConstants.captureScreenshots); + + // Build the toolID based on name and version + config.toolID = "java-accessibility-checker-v1.0.0"; + config.toolName = "java-accessibility-checker"; + config.toolVersion = "1.0.0"; + + // Using the uuid module generate a uuid number which is used to assoiciate to the scans that + // are done for a single run of karma. + config.scanID = java.util.UUID.randomUUID().toString(); + + for (Field field : ACConstants.getClass().getDeclaredFields()) { + try { + field.set(config, field.get(ACConstants)); + } catch (IllegalArgumentException e) { + } catch (IllegalAccessException e) { + } + } + + if (config.DEBUG) System.out.println("Config after initialization: "); + if (config.DEBUG) System.out.println(config); + + if (config.DEBUG) System.out.println("END 'initializeDefaults' function"); + } + + /** + * This function is responsible reading in the .yaml or .yml or .json and set the config options based on this. + * + * @return {Object} config - return the config object that was read in, refer to function initializeDefaults + * to view how the object is to be constructed. + * + * @memberOf this + */ + private static ConfigInternal loadConfigFromJSONFile() { + // Use an unpopulated config as the default values + ConfigInternal ACConstants = new ConfigInternal(); + + if (ACConstants.DEBUG) System.out.println("START 'loadConfigFromYAMLorJSONFile' function"); + + // Get the current working directory, where we will look for the yaml, yml or json file + String workingDir = System.getProperty("user.dir"); + if (ACConstants.DEBUG) System.out.println("Working directory set to: " + workingDir); + + String[] configFiles = ACConstants.configFiles; + + ConfigInternal config = null; + // Loop over all the possible location where the config file can reside, if one is found load it and break out. + for (String configFile: configFiles) { + // Get the full path to the config file we are going to check + String fileToCheck = Paths.get(workingDir, configFile).toString(); + + if (ACConstants.DEBUG) System.out.println("Checking file: " + fileToCheck); + + // Get the extension of the file we are about to scan + String fileExtension = fileToCheck.substring(fileToCheck.lastIndexOf('.') + 1); + + // If this is a yml or yaml file verify that the file exists and then load as such. + if ("json".equals(fileExtension)) { + if (ACConstants.DEBUG) System.out.println("Trying to load as json or js."); + + // Need to use try/catch mech so that in the case the require throws an exception, we can + // catch this and discatd the error, as in the case there is no config file provided then + // we load in default values. + try { + Gson gson = new Gson(); + JsonReader reader = new JsonReader(new FileReader(fileToCheck)); + config = gson.fromJson(reader, ConfigInternal.class); + } catch (FileNotFoundException e) { + if (ACConstants.DEBUG) System.out.println("JSON or JS file ("+fileToCheck+") does not exists, will load default config."); + } + } + } + + if (ACConstants.DEBUG) System.out.println("END 'loadConfigFromYAMLorJSONFile' function"); + + return config; + } + + /** + * This function is responsible for processing the karma configuration for accessibility-checker. + * The ACConfig provided in the Karma configuration will be processed by this + * function and then the config variables will be assoiciated to the global space so that + * they can be accessed from window.__karma__.config + * + * @param {Object} config - All the Karma configuration, we will extract what we need from this over + * all object, we need the entire object so that we can reasign some config + * variables to global scope so that all karma testscases/scripts can access + * them. + * + * @return - N/A - Object will be processed and all the params that are needed for this module will + * be extracted and then the entire object will be added to global space. + * + * @memberOf this + */ + private static ConfigInternal processConfiguration(Config config) { + // Use an unpopulated config as the default values + ConfigInternal ACConstants = new ConfigInternal(); + if (ACConstants.DEBUG) System.out.println("START 'processConfiguration' function"); + + // Variable Decleration + ConfigInternal ACConfig = null; + ConfigInternal configFromFile = null; + + // Read in the .yaml (.yml) or .json file to load in the configuration + configFromFile = loadConfigFromJSONFile(); + + if (ACConstants.DEBUG) System.out.println("Loaded config from file: "); + if (ACConstants.DEBUG) System.out.println(configFromFile); + + // In the case configuration was provided in a yaml, yml or json file, then set this as the configuration + // otherwise load them from the Karma configuration. + if (configFromFile != null) { + if (ACConstants.DEBUG) System.out.println("Using config which was loaded from config file."); + + ACConfig = configFromFile; + } else if (config != null) { + ACConfig = new ConfigInternal(config); + } else { + ACConfig = new ConfigInternal(); + } + + // In the case the ACConfig object is not defined, then define it with default config options so + // it can be set in window.__karma__.config.ACConfig, so that we know even in the testcases, other + // wrapper scripts that there was nothing defined at all, and at the same time to make sure that this + // code was actually executed. + initializeDefaults(ACConfig); + + // Now we process the final accessibility-checker config object that is build to make sure it is valid, also need to perform some + // mapping for provided paremeters to actualy read by the engine. + try { + ACConfig = processACConfig(ACConfig); + } catch (IOException e) { + System.err.println(e); + } + + // In the case the Karma config is set to config.LOG_DEBUG then also enable the accessibility-checker debuging + ACConfig.DEBUG = ACConstants.DEBUG; + + if (ACConstants.DEBUG) System.out.println("END 'processConfiguration' function"); + return ACConfig; + } + + private static ConfigInternal config = null; + static void setConfig(Config inConfig) { + config = ACConfigManager.processConfiguration(inConfig); + // TODO: + // ReporterManager.setConfig(config); + } + + static Config getConfig() { + return ACConfigManager.getConfigUnsupported(); + } + + static ConfigInternal getConfigUnsupported() { + if (ACConfigManager.config == null) { + ACConfigManager.setConfig(null); + } + return config; + } +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Archive.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Archive.java new file mode 100644 index 000000000..28859bd63 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Archive.java @@ -0,0 +1,39 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.config; + +import java.util.HashMap; +import java.util.Map; + +public class Archive { + public static class Ruleset { + public String id; + public String name; + public String description; + } + + public String id; + public String name; + public String path; + public Ruleset[] policies; + public Map rulesets = new HashMap(); + + public String version; + public boolean latest; + public boolean sunset; + public String helpPath; + public String enginePath; +} \ No newline at end of file diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java index 9802f549a..ea89359fa 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java @@ -16,6 +16,21 @@ package com.ibm.able.config; public class Config { + Config() {} + + Config(Config other) { + this.ruleArchive = other.ruleArchive; + this.policies = other.policies.clone(); + this.failLevels = other.failLevels.clone(); + this.reportLevels = other.reportLevels.clone(); + this.outputFormat = other.outputFormat.clone(); + this.label = other.label.clone(); + this.outputFolder = other.outputFolder; + this.outputFilenameTimestamp = other.outputFilenameTimestamp; + this.baselineFolder = other.baselineFolder; + this.cacheFolder = other.cacheFolder; + this.extensions = other.extensions; + } /** * (optional) Specify the rule archive * @@ -61,13 +76,13 @@ public class Config { * (optional) Specify any labels that you would like associated to your scan * Default: [] */ - public String[] label; + public String[] label = null; /** * (optional) Where the scan results should be saved. * Default: "results" */ - public String outputFolder; + public String outputFolder = null; /** * (optional) Should the timestamp be included in the filename of the reports? diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java index 9f7a279d8..3b4f9af00 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java @@ -18,6 +18,14 @@ import java.nio.file.Paths; public class ConfigInternal extends Config { + ConfigInternal() { + super(); + } + + ConfigInternal(Config config) { + super(config); + } + /** * Run in debug mode */ @@ -26,12 +34,12 @@ public class ConfigInternal extends Config { /** * Spot to store parsed archive file */ - // ruleArchiveSet?: IArchive[] + public Archive[] ruleArchiveSet = null; /** * Label to expose to reports */ - public String ruleArchiveLabel; + public String ruleArchiveLabel = null; /** * (optional) Rule server to pull the rules from and to use for help @@ -42,22 +50,22 @@ public class ConfigInternal extends Config { /** * Path to the rule pack */ - public String rulePack; + public String rulePack = null; /** * Path within the archive */ - public String ruleArchivePath; + public String ruleArchivePath = null; /** * Version number of the selected archive */ - public String ruleArchiveVersion; + public String ruleArchiveVersion = null; /** * (optional) If the tool allows, should we capture screenshots */ - public boolean captureScreenshots = false; + public Boolean captureScreenshots = false; /** * (optional) If the tool allows, should we run headless @@ -79,11 +87,11 @@ public class ConfigInternal extends Config { Paths.get(".config", "aceconfig.json").toString() }; - public String toolID; - public String toolName; - public String toolVersion; + public String toolID = null; + public String toolName = null; + public String toolVersion = null; - public String scanID; + public String scanID = null; public boolean ignoreHTTPSErrors = false; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java new file mode 100644 index 000000000..ab9b1bf5b --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java @@ -0,0 +1,64 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.util; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import com.google.gson.Gson; + +public class Fetch { + private Fetch() {} + + private static Gson gson = new Gson(); + + public static String get(String urlStr) throws IOException { + URL url = new URL(urlStr); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + + con.setDoOutput(true); + DataOutputStream out = new DataOutputStream(con.getOutputStream()); + out.flush(); + out.close(); + return out.toString(); + } + + public static T[] getJSONArr(String urlStr, Class clazz) throws IOException { + URL url = new URL(urlStr); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + + con.setDoOutput(true); + DataOutputStream out = new DataOutputStream(con.getOutputStream()); + out.flush(); + out.close(); + return gson.fromJson(out.toString(), clazz); + } + + public static T getJSONObj(String urlStr, Class clazz) throws IOException { + URL url = new URL(urlStr); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + + con.setDoOutput(true); + DataOutputStream out = new DataOutputStream(con.getOutputStream()); + out.flush(); + out.close(); + return gson.fromJson(out.toString(), clazz); + } +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java new file mode 100644 index 000000000..46639123e --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java @@ -0,0 +1,28 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.util; + +public class Misc { + private Misc() {} + + public static T firstNotNull(T ... args) { + for (T x : args) { + if (x != null) return x; + } + return null; + } + +} From 2936c7dfdd831fd1ae83c88d018765e96586930e Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 6 Aug 2024 14:00:30 -0500 Subject: [PATCH 005/161] Process config files --- .../com/ibm/able/config/ACConfigManager.java | 59 +++-- .../java/com/ibm/able/config/Archive.java | 2 +- .../main/java/com/ibm/able/config/Config.java | 2 +- .../main/java/com/ibm/able/util/Fetch.java | 40 +-- .../test/java/com/ibm/able/LibraryTest.java | 3 +- .../ibm/able/config/ACConfigManagerTest.java | 245 ++++++++++++++++++ .../java/com/ibm/able/util/FetchTest.java | 23 ++ 7 files changed, 320 insertions(+), 54 deletions(-) create mode 100644 java-accessibility-checker/lib/src/test/java/com/ibm/able/config/ACConfigManagerTest.java create mode 100644 java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java index 86a969b53..2c2329012 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java @@ -22,12 +22,10 @@ import java.lang.reflect.Field; import java.nio.file.Paths; import java.util.Arrays; -import java.util.List; import java.util.regex.Pattern; import com.google.gson.Gson; import com.google.gson.stream.JsonReader; -import com.ibm.able.config.Archive; import com.ibm.able.util.Fetch; import com.ibm.able.util.Misc; @@ -49,8 +47,8 @@ private static String[] covertPolicies(String policies) { * @param versionA * @param versionB */ - private static int compareVersions(String versionA, String versionB) { - Pattern versionRE = Pattern.compile("[0-9.]+(-rc.[0-9]+)?"); + public static int compareVersions(String versionA, String versionB) { + Pattern versionRE = Pattern.compile("[0-9.]+(-rc\\.[0-9]+)?"); versionA = versionA.trim(); versionB = versionB.trim(); if (!versionRE.matcher(versionA).matches()) throw new ConfigError("Invalid version"); @@ -58,15 +56,16 @@ private static int compareVersions(String versionA, String versionB) { if (versionA.equals(versionB)) return 0; // Get x.y.z-rc.a into [x.y.z, a] // Get x.y.z into [x.y.z] - String[] split1A = versionA.split("-rc."); - String[] split1B = versionB.split("-rc."); + String[] split1A = versionA.split("-rc\\."); + String[] split1B = versionB.split("-rc\\."); // Get x.y.z into [x,y,z] - String[] split2A = split1A[0].split("."); - String[] split2B = split1B[0].split("."); + String[] split2A = split1A[0].split("\\."); + String[] split2B = split1B[0].split("\\."); + // For the components of the shortest version - can only compare numbers we have int minLength = Math.min(split2A.length, split2B.length); for (int idx=0; idx rulesets = new HashMap(); + public Map rulesets = new HashMap(); public String version; public boolean latest; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java index ea89359fa..10553a960 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java @@ -82,7 +82,7 @@ public class Config { * (optional) Where the scan results should be saved. * Default: "results" */ - public String outputFolder = null; + public String outputFolder = "results"; /** * (optional) Should the timestamp be included in the filename of the reports? diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java index ab9b1bf5b..74ca68891 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java @@ -15,8 +15,9 @@ *****************************************************************************/ package com.ibm.able.util; -import java.io.DataOutputStream; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import com.google.gson.Gson; @@ -28,37 +29,22 @@ private Fetch() {} public static String get(String urlStr) throws IOException { URL url = new URL(urlStr); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - con.setRequestMethod("GET"); - - con.setDoOutput(true); - DataOutputStream out = new DataOutputStream(con.getOutputStream()); - out.flush(); - out.close(); - return out.toString(); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream()))); + StringBuilder sb = new StringBuilder(); + String output; + while ((output = br.readLine()) != null) { + sb.append(output); + } + return sb.toString(); } public static T[] getJSONArr(String urlStr, Class clazz) throws IOException { - URL url = new URL(urlStr); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - con.setRequestMethod("GET"); - - con.setDoOutput(true); - DataOutputStream out = new DataOutputStream(con.getOutputStream()); - out.flush(); - out.close(); - return gson.fromJson(out.toString(), clazz); + return gson.fromJson(Fetch.get(urlStr), clazz); } public static T getJSONObj(String urlStr, Class clazz) throws IOException { - URL url = new URL(urlStr); - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - con.setRequestMethod("GET"); - - con.setDoOutput(true); - DataOutputStream out = new DataOutputStream(con.getOutputStream()); - out.flush(); - out.close(); - return gson.fromJson(out.toString(), clazz); + return gson.fromJson(Fetch.get(urlStr), clazz); } } diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java index 48995cf39..4f6c5ac53 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java @@ -36,7 +36,8 @@ public class LibraryTest { @Test public void someLibraryMethodReturnsTrue() { LibraryTest.driver.get("https://altoromutual.12mc9fdq8fib.us-south.codeengine.appdomain.cloud/"); String pageTitle = driver.getTitle(); - System.out.println("Page Title: " + pageTitle); + System.out.println("Page Title: " + pageTitle); + System.out.println(System.getProperty("user.dir")); Library classUnderTest = new Library(); assertTrue("someLibraryMethod should return 'true'", classUnderTest.someLibraryMethod()); } diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/config/ACConfigManagerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/config/ACConfigManagerTest.java new file mode 100644 index 000000000..c152c2619 --- /dev/null +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/config/ACConfigManagerTest.java @@ -0,0 +1,245 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ + +package com.ibm.able.config; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.regex.Pattern; + +import org.junit.Test; + +public class ACConfigManagerTest { + @Test public void getConfigWithNoConfigFile() { + Config config = ACConfigManager.getConfig(); + + // Main properties + assertEquals("latest", config.ruleArchive); + assertArrayEquals(new String[] { "IBM_Accessibility" }, config.policies); + assertArrayEquals(new String[] { "violation", "potentialviolation" }, config.failLevels); + assertArrayEquals(new String[] { "violation", "potentialviolation" }, config.reportLevels); + assertArrayEquals(new String[] { "json" }, config.outputFormat); + assertArrayEquals(null, config.label); + assertEquals("results", config.outputFolder); + assertEquals(true, config.outputFilenameTimestamp); + assertEquals("baselines", config.baselineFolder); + assertEquals(System.getProperty("java.io.tmpdir")+"/accessibility-checker/", config.cacheFolder); + assertArrayEquals(new String[] { "html", "htm", "svg" }, config.extensions); + + // Internal properties + assertTrue(config instanceof ConfigInternal); + ConfigInternal configInternal = (ConfigInternal) config; + + assertEquals(false, configInternal.DEBUG); + assertEquals("latest", configInternal.ruleArchiveSet[0].id); + assertEquals("Latest Deployment (latest)", configInternal.ruleArchiveLabel); + assertEquals("https://cdn.jsdelivr.net/npm/accessibility-checker-engine", configInternal.ruleServer); + assertEquals("https://cdn.jsdelivr.net/npm/accessibility-checker-engine", configInternal.rulePack.split("@")[0]); + assertEquals("/archives/", configInternal.ruleArchivePath.substring(0, "/archives/".length())); + assertEquals(3, configInternal.ruleArchiveVersion.split("\\.").length); + assertEquals(false, configInternal.captureScreenshots); + assertEquals(true, configInternal.headless); + assertEquals(1, configInternal.maxTabs); + assertArrayEquals(new String[] { + "achecker.json", + "aceconfig.json", + Paths.get(".config", "achecker.json").toString(), + Paths.get(".config", "aceconfig.json").toString() + }, configInternal.configFiles); + assertEquals("java-accessibility-checker-v3.1.70", configInternal.toolID); + assertEquals("java-accessibility-checker", configInternal.toolName); + assertEquals("3.1.70", configInternal.toolVersion); + Pattern uuidPattern = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); + assertTrue(uuidPattern.matcher(configInternal.scanID).matches()); + assertEquals(false, configInternal.ignoreHTTPSErrors); + assertEquals(true, configInternal.perfMetrics); + assertEquals("DEFAULT", configInternal.engineMode); + } + + @Test public void getConfigWithConfigFile() throws IOException { + ACConfigManager.resetConfig(); + File configFile = new File("achecker.json"); + try { + configFile.delete(); + FileWriter myWriter = new FileWriter("achecker.json"); + myWriter.write(""" +{ + "ruleArchive": "17June2024", + "policies": [ "IBM_Accessibility"], + "failLevels": [ "violation" ], + "reportLevels": [ + "violation", + "potentialviolation", + "recommendation", + "potentialrecommendation", + "manual" + ], + "outputFormat": [ "json", "xlsx" ], + "label": [ + "Java", + "Demo" + ], + "outputFolder": ".aat/results", + "baselineFolder": ".aat/baselines" +} +"""); + myWriter.close(); + + Config config = ACConfigManager.getConfig(); + + // Main properties + assertEquals("17June2024", config.ruleArchive); + assertArrayEquals(new String[] { "IBM_Accessibility" }, config.policies); + assertArrayEquals(new String[] { "violation" }, config.failLevels); + assertArrayEquals(new String[] { "violation", "potentialviolation", "recommendation", "potentialrecommendation", "manual" }, config.reportLevels); + assertArrayEquals(new String[] { "json", "xlsx" }, config.outputFormat); + assertArrayEquals(new String[] { "Java", "Demo" }, config.label); + assertEquals(".aat/results", config.outputFolder); + assertEquals(true, config.outputFilenameTimestamp); + assertEquals(".aat/baselines", config.baselineFolder); + assertEquals(System.getProperty("java.io.tmpdir")+"/accessibility-checker/", config.cacheFolder); + assertArrayEquals(new String[] { "html", "htm", "svg" }, config.extensions); + + // Internal properties + assertTrue(config instanceof ConfigInternal); + ConfigInternal configInternal = (ConfigInternal) config; + + assertEquals(false, configInternal.DEBUG); + assertEquals("latest", configInternal.ruleArchiveSet[0].id); + assertEquals("17 June 2024 Deployment (IBM 7.2, 7.3) (17June2024)", configInternal.ruleArchiveLabel); + assertEquals("https://cdn.jsdelivr.net/npm/accessibility-checker-engine", configInternal.ruleServer); + assertEquals("https://cdn.jsdelivr.net/npm/accessibility-checker-engine", configInternal.rulePack.split("@")[0]); + assertEquals("/archives/", configInternal.ruleArchivePath.substring(0, "/archives/".length())); + assertEquals(3, configInternal.ruleArchiveVersion.split("\\.").length); + assertEquals(false, configInternal.captureScreenshots); + assertEquals(true, configInternal.headless); + assertEquals(1, configInternal.maxTabs); + assertArrayEquals(new String[] { + "achecker.json", + "aceconfig.json", + Paths.get(".config", "achecker.json").toString(), + Paths.get(".config", "aceconfig.json").toString() + }, configInternal.configFiles); + assertEquals("java-accessibility-checker-v3.1.70", configInternal.toolID); + assertEquals("java-accessibility-checker", configInternal.toolName); + assertEquals("3.1.70", configInternal.toolVersion); + Pattern uuidPattern = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); + assertTrue(uuidPattern.matcher(configInternal.scanID).matches()); + assertEquals(false, configInternal.ignoreHTTPSErrors); + assertEquals(true, configInternal.perfMetrics); + assertEquals("DEFAULT", configInternal.engineMode); + } finally { + configFile.delete(); + } + } + + @Test public void getConfigWithConfigFileVersioned() throws IOException { + ACConfigManager.resetConfig(); + File configFile = new File("achecker.json"); + try { + configFile.delete(); + FileWriter myWriter = new FileWriter("achecker.json"); + myWriter.write(""" +{ + "ruleArchive": "versioned", + "policies": [ "IBM_Accessibility"], + "failLevels": [ "violation" ], + "reportLevels": [ + "violation", + "potentialviolation", + "recommendation", + "potentialrecommendation", + "manual" + ], + "outputFormat": [ "json", "xlsx" ], + "label": [ + "Java", + "Demo" + ], + "outputFolder": ".aat/results", + "baselineFolder": ".aat/baselines" +} +"""); + myWriter.close(); + + Config config = ACConfigManager.getConfig(); + + // Main properties + assertEquals("versioned", config.ruleArchive); + assertArrayEquals(new String[] { "IBM_Accessibility" }, config.policies); + assertArrayEquals(new String[] { "violation" }, config.failLevels); + assertArrayEquals(new String[] { "violation", "potentialviolation", "recommendation", "potentialrecommendation", "manual" }, config.reportLevels); + assertArrayEquals(new String[] { "json", "xlsx" }, config.outputFormat); + assertArrayEquals(new String[] { "Java", "Demo" }, config.label); + assertEquals(".aat/results", config.outputFolder); + assertEquals(true, config.outputFilenameTimestamp); + assertEquals(".aat/baselines", config.baselineFolder); + assertEquals(System.getProperty("java.io.tmpdir")+"/accessibility-checker/", config.cacheFolder); + assertArrayEquals(new String[] { "html", "htm", "svg" }, config.extensions); + + // Internal properties + assertTrue(config instanceof ConfigInternal); + ConfigInternal configInternal = (ConfigInternal) config; + + assertEquals(false, configInternal.DEBUG); + assertEquals("latest", configInternal.ruleArchiveSet[0].id); + assertEquals("19 April 2024 Deployment (IBM 7.2) (19April2024)", configInternal.ruleArchiveLabel); + assertEquals("https://cdn.jsdelivr.net/npm/accessibility-checker-engine", configInternal.ruleServer); + assertEquals("https://cdn.jsdelivr.net/npm/accessibility-checker-engine", configInternal.rulePack.split("@")[0]); + assertEquals("/archives/", configInternal.ruleArchivePath.substring(0, "/archives/".length())); + assertEquals(3, configInternal.ruleArchiveVersion.split("\\.").length); + assertEquals(false, configInternal.captureScreenshots); + assertEquals(true, configInternal.headless); + assertEquals(1, configInternal.maxTabs); + assertArrayEquals(new String[] { + "achecker.json", + "aceconfig.json", + Paths.get(".config", "achecker.json").toString(), + Paths.get(".config", "aceconfig.json").toString() + }, configInternal.configFiles); + assertEquals("java-accessibility-checker-v3.1.70", configInternal.toolID); + assertEquals("java-accessibility-checker", configInternal.toolName); + assertEquals("3.1.70", configInternal.toolVersion); + Pattern uuidPattern = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); + assertTrue(uuidPattern.matcher(configInternal.scanID).matches()); + assertEquals(false, configInternal.ignoreHTTPSErrors); + assertEquals(true, configInternal.perfMetrics); + assertEquals("DEFAULT", configInternal.engineMode); + } finally { + configFile.delete(); + } + } + + @Test public void compareVersions() throws IOException { + assertTrue(ACConfigManager.compareVersions("1.0.0", "1.0.0") == 0); + assertTrue(ACConfigManager.compareVersions("1.0.1", "1.0.0") > 0); + assertTrue(ACConfigManager.compareVersions("1.1.0", "1.0.0") > 0); + assertTrue(ACConfigManager.compareVersions("2.0.0", "1.0.0") > 0); + assertTrue(ACConfigManager.compareVersions("1.0.0", "1.0.1") < 0); + assertTrue(ACConfigManager.compareVersions("1.0.0", "1.1.0") < 0); + assertTrue(ACConfigManager.compareVersions("1.0.0", "2.0.0") < 0); + assertTrue(ACConfigManager.compareVersions("1.0.0", "1.0.0-rc.0") > 0); + assertTrue(ACConfigManager.compareVersions("1.0.0-rc.1", "1.0.0-rc.0") > 0); + assertTrue(ACConfigManager.compareVersions("1.0.0-rc.0", "1.0.0") < 0); + assertTrue(ACConfigManager.compareVersions("1.0.0-rc.0", "1.0.0-rc.1") < 0); + } +} \ No newline at end of file diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java new file mode 100644 index 000000000..9cb22c9ee --- /dev/null +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java @@ -0,0 +1,23 @@ +/* + * This source file was generated by the Gradle 'init' task + */ +package com.ibm.able.util; + +import org.junit.Test; +import static org.junit.Assert.*; + +import java.io.IOException; + +import com.ibm.able.util.Fetch; + +public class FetchTest { + @Test public void getArr() { + String s = null; + try { + s = Fetch.get("https://cdn.jsdelivr.net/npm/accessibility-checker-engine@next/archives.json"); + } catch (IOException e) { + e.printStackTrace(); + } + assertEquals(String.class, s.getClass()); + } +} From 62c54007a3dd2d29c1c40de64e208b4bc26cc9dd Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Wed, 7 Aug 2024 10:17:38 -0500 Subject: [PATCH 006/161] Report signs of life --- .../com/ibm/able/AccessibilityChecker.java | 246 ++++++++++++++++++ .../com/ibm/able/EngineContextManager.java | 30 +++ .../java/com/ibm/able/IEngineContext.java | 26 ++ .../com/ibm/able/config/ACConfigManager.java | 8 +- .../java/com/ibm/able/engine/ACError.java | 8 + .../java/com/ibm/able/engine/ACReport.java | 47 ++++ .../able/selenium/EngineContextSelenium.java | 193 ++++++++++++++ .../src/main/java/com/ibm/able/util/Misc.java | 9 + .../ibm/able/AccessibilityCheckerTest.java | 53 ++++ .../test/java/com/ibm/able/LibraryTest.java | 44 ---- 10 files changed, 616 insertions(+), 48 deletions(-) create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/EngineContextManager.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/IEngineContext.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/selenium/EngineContextSelenium.java create mode 100644 java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java delete mode 100644 java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java new file mode 100644 index 000000000..422366a54 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java @@ -0,0 +1,246 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able; + +import java.io.IOException; +import com.ibm.able.config.ACConfigManager; +import com.ibm.able.config.Config; +import com.ibm.able.engine.ACReport; + +public class AccessibilityChecker { + /** + * This function is responsible performing a scan based on the context that is provided, following are + * the supported context type: + * Single node (HTMLElement) + * Local file path (String) + * URL (String) + * document node + * data stream for html content (String) + * + * Future Items + * Multiple node (Array of HTMLElements) ---> FUTURE + * + * @param {(Webdriver|Puppeteer Page |)} content - Provide the context to scan, which includes the items from above. + * @param {String} label - Provide a label for the scan that is being performed + * @param {Function} callback - (optional) Provide callback function which will be executed once the results are extracted. + * @return Promise with the ICheckerResult + */ + public static ACReport getCompliance(Object content, String label) { + if (content == null) { + System.err.println("aChecker: Unable to get compliance of null or undefined object"); + return null; + } + + AccessibilityChecker.initialize(); + + IEngineContext engineContext = EngineContextManager.getEngineContext(content); + try { + engineContext.loadEngine(); + } catch (IOException e) { + System.err.println("aChecker: Unable to load engine due to IOException: "+e.toString()); + e.printStackTrace(); + } + + // Get the Data when the scan is started + // Start time will be in milliseconds elapsed since 1 January 1970 00:00:00 UTC up until now. + return engineContext.getCompliance(label); + } + + public static Config getConfig() { + return ACConfigManager.getConfig(); + } + + public static Config getConfigUnsupported() { + return ACConfigManager.getConfigUnsupported(); + } + + private static void initialize() { + // TODO: + // if (Config) return; + // Config = await ACConfigManager.getConfigUnsupported(); + // await ACEngineManager.loadEngineLocal(); + // let absAPI = new MyFS(); + // let refactorMap : RefactorMap = {} + // let rules = ACEngineManager.getRulesSync(); + // for (const rule of rules) { + // if (rule.refactor) { + // for (const key in rule.refactor) { + // refactorMap[key] = rule; + // } + // } + // } + // ReporterManager.initialize(Config, absAPI, await ACEngineManager.getRulesets()); + // BaselineManager.initialize(Config, absAPI, refactorMap); + } + +// /** +// * This function is responsible for comparing the scan results with baseline or checking that there are +// * no violations which fall into the failsLevels levels. In the case a baseline is found then baseline will +// * be used to perform the check, in the case no baseline is provided then we comply with only failing if +// * there is a sinble violation which falls into failLevels. +// * +// * @param {ReportResult} actual - the actual results object provided by the user, this object should follow the +// * same format as outlined in the return of aChecker.buildReport function. +// * +// * @return {int} - return 0 in the case actual matches baseline or no violations fall into failsLevels, +// * return 1 in the case actual results does not match baseline results, +// * return 2 in the case that there is a failure based on failLevels (this means no baseline found). +// * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. +// */ +// export function assertCompliance(report: IBaselineReport) : eAssertResult { +// return BaselineManager.assertCompliance(report) +// } + +// /** +// * This function is responsible for printing the scan results to console. +// * +// * @param {Object} results - Provide the results from the scan. +// * +// * @return {String} resultsString - String representation of the results/violations. +// * +// * PUBLIC API +// * +// * @memberOf this +// */ +// export function stringifyResults(report: ICheckerReport) : string { +// return ReporterManager.stringifyResults(report) +// } + +// export function close() { +// return ACBrowserManager.close(); +// } + +// /** +// * This function is responsible for getting the diff results based on label for a scan that was already performed. +// * +// * @param {String} label - Provide a lable for which to get the diff results for. +// * +// * @return {Object} - return the diff results object from global space based on label provided, the object will be +// * in the same format as outlined in the return of aChecker.diffResultsWithExpected function. +// */ +// export function getDiffResults(label: string) { +// return BaselineManager.getDiffResults(label); +// } + +// /** +// * This function is responsible for getting the baseline object for a label that was provided. +// * +// * @param {String} label - Provide a lable for which to get the baseline for. +// * +// * @return {Object} - return the baseline object from global space based on label provided, the object will be +// * in the same format as outlined in the return of aChecker.buildReport function. +// */ +// export function getBaseline(label: string) { +// return BaselineManager.getBaseline(label); +// } + +// /** +// * This function is responsible for comparing actual with expected and returning all the differences as an array. +// * +// * @param {Object} actual - Provide the actual object to be used for compare +// * @param {Object} expected - Provide the expected object to be used for compare +// * @param {boolean} clean - Provide a boolean if both the actual and expected objects need to be cleaned +// * cleaning refers to converting the objects to match with a basic compliance +// * compare of xpath and ruleId. +// * +// * @return {Object} differences - return an array of diff objects that were found, following is the format of the object: +// * [ +// * { +// * "kind": "E", +// * "path": [ +// * "reports", +// * 0, +// * "issues", +// * 10, +// * "xpath" +// * ], +// * "lhs": "/html[1]/body[1]/div[2]/table[5]", +// * "rhs": "/html[1]/body[1]/div[2]/table[5]d", +// * }, +// * { +// * "kind": "E", +// * "path": [ +// * "label" +// * ], +// * "lhs": "Table-layoutMultiple", +// * "rhs": "dependencies/tools-rules-html/v2/a11y/test/g471/Table-layoutMultiple.html", +// * } +// * ] +// */ +// export function diffResultsWithExpected(actual, expected, clean) { +// return BaselineManager.diffResultsWithExpected(actual, expected, clean); +// } + +// /** +// * This function is responsible for cleaning up the compliance baseline or actual results, based on +// * a pre-defined set of criterias, such as the following: +// * 1. No need to compare summary object +// * 2. Only need to compare the ruleId and xpath in for each of the issues +// * +// * @param {Object} objectToClean - Provide either an baseline or actual results object which would be in the +// * the same format as outlined in the return of aChecker.buildReport function. +// * +// * @return {Object} objectToClean - return an object that was cleaned to only contain the information that is +// * needed for compare. Following is a sample of how the cleaned object will look like: +// * { +// * "label": "unitTestContent", +// * "reports": [ +// * { +// * "frameIdx": "0", +// * "frameTitle": "Frame 0", +// * "issues": [ +// * { +// * "ruleId": "1", +// * "xpath": "/html[1]/head[1]/style[1]" +// * } +// * .... +// * ] +// * }, +// * { +// * "frameIdx": "1", +// * "frameTitle": "Frame 1", +// * "issues": [ +// * { +// * "ruleId": "471", +// * "xpath": "/html[1]/body[1]/div[2]/table[3]" +// * } +// * .... +// * ] +// * } +// * ] +// * } +// */ +// export function cleanComplianceObjectBeforeCompare(objectToClean) { +// return BaselineManager.cleanComplianceObjectBeforeCompare(objectToClean); +// } + +// export function addRuleset(ruleset) { +// ACEngineManager.addRuleset(ruleset); +// } + +// export async function getRuleset(rsId) { +// return ACEngineManager.getRuleset(rsId); +// }; + +// export async function getRulesets() { +// return ACEngineManager.getRulesets(); +// }; + +// export async function getRules() { +// return ACEngineManager.getRules(); +// } + +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/EngineContextManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/EngineContextManager.java new file mode 100644 index 000000000..b0b935ebc --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/EngineContextManager.java @@ -0,0 +1,30 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able; + +import org.openqa.selenium.WebDriver; + +import com.ibm.able.selenium.EngineContextSelenium; +import com.ibm.able.util.Misc; + +public class EngineContextManager { + public static IEngineContext getEngineContext(Object contentContext) { + if (Misc.classIsAvailable("org.openqa.selenium.WebDriver") && contentContext instanceof org.openqa.selenium.WebDriver) { + return new EngineContextSelenium((WebDriver) contentContext); + } + return null; + } +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/IEngineContext.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/IEngineContext.java new file mode 100644 index 000000000..1ad11b3a7 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/IEngineContext.java @@ -0,0 +1,26 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able; + +import java.io.IOException; + +import com.ibm.able.engine.ACReport; + +public interface IEngineContext { + void loadEngine() throws IOException; + + ACReport getCompliance(String label); +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java index 2c2329012..03e843937 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java @@ -363,24 +363,24 @@ private static ConfigInternal processConfiguration(Config config) { } private static ConfigInternal config = null; - static void setConfig(Config inConfig) { + public static void setConfig(Config inConfig) { config = ACConfigManager.processConfiguration(inConfig); // TODO: // ReporterManager.setConfig(config); } - static Config getConfig() { + public static Config getConfig() { return ACConfigManager.getConfigUnsupported(); } - static ConfigInternal getConfigUnsupported() { + public static ConfigInternal getConfigUnsupported() { if (ACConfigManager.config == null) { ACConfigManager.setConfig(null); } return config; } - static void resetConfig() { + public static void resetConfig() { config = null; } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java new file mode 100644 index 000000000..0be8b61f1 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java @@ -0,0 +1,8 @@ +package com.ibm.able.engine; + +public class ACError extends Error { + public ACError(String msg) { + super(msg); + } + +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java new file mode 100644 index 000000000..68b1494c9 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java @@ -0,0 +1,47 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ + +package com.ibm.able.engine; +import java.util.Map; + +public class ACReport { + public static class Bounds { + int top; + int left; + int height; + int width; + } + + public static class Result { + public Object[] apiArgs; + public Bounds bounds; + public String category; + public String message; + public String[] messageArgs; + public Map path; + public String reasonId; + public String ruleId; + public int ruleTime; + public String snippet; + public String[] value; + } + + public int numExecuted; + public int ruleTime; + public int totalTime; + public Map> nls; + public Result[] results; +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/selenium/EngineContextSelenium.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/selenium/EngineContextSelenium.java new file mode 100644 index 000000000..0030c94ff --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/selenium/EngineContextSelenium.java @@ -0,0 +1,193 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.selenium; + +import java.io.IOException; +import java.time.Duration; +import java.util.Date; + +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebDriver; + +import com.google.gson.Gson; +import com.ibm.able.IEngineContext; +import com.ibm.able.config.ACConfigManager; +import com.ibm.able.config.Config; +import com.ibm.able.config.ConfigInternal; +import com.ibm.able.engine.ACError; +import com.ibm.able.engine.ACReport; +import com.ibm.able.util.Fetch; + +public class EngineContextSelenium implements IEngineContext { + private WebDriver driver = null; + private String engineContent = null; + + public EngineContextSelenium(WebDriver driver) { + this.driver = driver; + } + + public void loadEngine() throws IOException { + ConfigInternal config = ACConfigManager.getConfigUnsupported(); + String engineLoadMode = config.engineMode; + if ("DEFAULT".equals(engineLoadMode)) { + engineLoadMode = "INJECT"; + } + if ("INJECT".equals(engineLoadMode) && engineContent == null) { + engineContent = Fetch.get(config.rulePack+"/ace.js"); + } + + if (config.DEBUG) System.out.println("[INFO] aChecker.loadEngine detected Selenium"); + try { + String scriptStr; + if ("REMOTE".equals(engineLoadMode)) { + scriptStr = String.format(""" +let cb = arguments[arguments.length - 1]; +try { + var ace_backup_in_ibma; + if ('undefined' !== typeof(ace)) { + if (!ace || !ace.Checker) + ace_backup_in_ibma = ace; + ace = null; + } + if ('undefined' === typeof (ace) || ace === null) { + let script = document.createElement('script'); + script.setAttribute('type', 'text/javascript'); + script.setAttribute('aChecker', 'ACE'); + script.setAttribute('src', '%s/ace.js'); + script.addEventListener('load', function() { + globalThis.ace_ibma = ace; + if ('undefined' !== typeof(ace)) { + ace = ace_backup_in_ibma; + } + cb(); + }); + let heads = document.getElementsByTagName('head'); + if (heads.length > 0) { heads[0].appendChild(script); } + else { document.body.appendChild(script); } + } else { + cb(); + } +} catch (e) { + cb(e); +} +""", config.rulePack); + } else if ("INJECT".equals(engineLoadMode)) { + Gson gson = new Gson(); + // Selenium + scriptStr = String.format(""" +let cb = arguments[arguments.length - 1]; +try { + var ace_backup_in_ibma; + if ('undefined' !== typeof(ace)) { + if (!ace || !ace.Checker) + ace_backup_in_ibma = ace; + ace = null; + } + if ('undefined' === typeof (ace) || ace === null) { + eval(%s) + globalThis.ace_ibma = ace; + if ('undefined' !== typeof(ace)) { + ace = ace_backup_in_ibma; + } + cb(); + + } else { + cb(); + } +} catch (e) { + cb(e); +} +""", gson.toJson(engineContent)); + } else { + scriptStr = ""; + } + + this.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(60)); + + Object result = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr); + if (result != null) { + System.err.println(result); + } + } catch (Error e) { + System.err.println(e); + } + } + + public ACReport getCompliance(String label) { + Config config = ACConfigManager.getConfig(); + Gson gson = new Gson(); + try { + Date startScan = new Date(); + String scriptStr = String.format(""" +let cb = arguments[arguments.length - 1]; +try { + let policies = %s; + + let checker = new window.ace_ibma.Checker(); + let customRulesets = []; + customRulesets.forEach((rs) => checker.addRuleset(rs)); + setTimeout(function() { + checker.check(document, policies).then(function(report) { + for (const result of report.results) { + delete result.node; + } + cb(JSON.stringify(report)); + }) + },0) +} catch (e) { + cb(e); +} + """, gson.toJson(config.policies) /* TODO: ${JSON.stringify(ACEngineManager.customRulesets)}; */); + this.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(60)); + + String jsonReport = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr).toString(); + if (!jsonReport.startsWith("{\"results\":[")) { + throw new ACError(jsonReport); + } else { + return gson.fromJson(jsonReport, ACReport.class); + } + // TODO: + // String getPolicies = "return new window.ace_ibma.Checker().rulesetIds;"; + // if (curPol != null && !checkPolicy) { + // checkPolicy = true; + // const valPolicies = ACEngineManager.customRulesets.map(rs => rs.id).concat(await browser.executeScript(getPolicies)); + // areValidPolicy(valPolicies, curPol); + // } + + // // If there is something to report... + // let finalReport : IBaselineReport; + // if (report.results) { + // // Add URL to the result object + // const url = await browser.getCurrentUrl(); + // const title = await browser.getTitle(); + // let origReport : IEngineReport = JSON.parse(JSON.stringify(report)); + // if (Config.captureScreenshots && browser.takeScreenshot) { + // const image = await browser.takeScreenshot(); + // origReport.screenshot = image; + // } + // finalReport = ReporterManager.addEngineReport("Selenium", startScan, url, title, label, origReport); + // } + // return { + // "report": finalReport, + // "webdriver": parsed + // } + } catch (Error err) { + System.err.println(err); + throw err; + } + } + +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java index 46639123e..8d6365617 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java @@ -25,4 +25,13 @@ public static T firstNotNull(T ... args) { return null; } + public static boolean classIsAvailable(String className) { + try { + Class.forName(className); + return true; + } catch (Throwable ex) { + // Class or one of its dependencies is not present... + return false; + } + } } diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java new file mode 100644 index 000000000..da5ec64c2 --- /dev/null +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -0,0 +1,53 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able; + +import org.junit.Test; +import static org.junit.Assert.*; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.openqa.selenium.chrome.ChromeDriver; + +import com.ibm.able.engine.ACReport; + +public class AccessibilityCheckerTest { + private static ChromeDriver driver; + + /** + * Setup a Selenium Chrome environment before tests + */ + @BeforeClass public static void setup() { + String workingDir = System.getProperty("user.dir"); + String chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; + System.setProperty("webdriver.chrome.driver", chromeDriverDir); + AccessibilityCheckerTest.driver = new ChromeDriver(); + } + + /** + * Close Selenium Chrome environment after tests + */ + @AfterClass public static void teardown() { + AccessibilityCheckerTest.driver.close(); + } + + @Test public void getCompliance() { + AccessibilityCheckerTest.driver.get("https://altoromutual.12mc9fdq8fib.us-south.codeengine.appdomain.cloud/"); + ACReport report = AccessibilityChecker.getCompliance(driver, "getComplianceTest"); + assertNotNull(report); + assertTrue(report.results.length > 0); + } +} diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java deleted file mode 100644 index 4f6c5ac53..000000000 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/LibraryTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This source file was generated by the Gradle 'init' task - */ -package com.ibm.able; - -import org.junit.Test; -import static org.junit.Assert.*; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -// import org.openqa.selenium.WebDriver; -import org.openqa.selenium.chrome.ChromeDriver; - -import com.ibm.able.Library; - -public class LibraryTest { - private static ChromeDriver driver; - - /** - * Setup a Selenium Chrome environment before tests - */ - @BeforeClass public static void setup() { - String workingDir = System.getProperty("user.dir"); - String chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; - System.setProperty("webdriver.chrome.driver", chromeDriverDir); - LibraryTest.driver = new ChromeDriver(); - } - - /** - * Close Selenium Chrome environment after tests - */ - @AfterClass public static void teardown() { - LibraryTest.driver.close(); - } - - @Test public void someLibraryMethodReturnsTrue() { - LibraryTest.driver.get("https://altoromutual.12mc9fdq8fib.us-south.codeengine.appdomain.cloud/"); - String pageTitle = driver.getTitle(); - System.out.println("Page Title: " + pageTitle); - System.out.println(System.getProperty("user.dir")); - Library classUnderTest = new Library(); - assertTrue("someLibraryMethod should return 'true'", classUnderTest.someLibraryMethod()); - } -} From 5464d6cf6a542a54c251d1253d6b60cbeadf9247 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Thu, 8 Aug 2024 14:52:28 -0500 Subject: [PATCH 007/161] First report --- java-accessibility-checker/lib/.gitignore | 1 + java-accessibility-checker/lib/build.gradle | 2 + .../com/ibm/able/AccessibilityChecker.java | 37 +-- .../IAbstractAPI.java} | 9 +- .../src/main/java/com/ibm/able/abs/MyFS.java | 54 +++++ .../main/java/com/ibm/able/config/Config.java | 5 + .../com/ibm/able/config/ConfigInternal.java | 5 - .../java/com/ibm/able/engine/ACEReport.java | 56 +++++ .../java/com/ibm/able/engine/ACError.java | 15 ++ .../java/com/ibm/able/engine/ACReport.java | 174 ++++++++++++-- .../com/ibm/able/engine/ACReportSummary.java | 86 +++++++ .../main/java/com/ibm/able/engine/Bounds.java | 23 ++ .../java/com/ibm/able/engine/Guideline.java | 39 ++++ .../eRuleConfidence.java} | 30 ++- .../java/com/ibm/able/engine/eRuleLevel.java | 42 ++++ .../enginecontext/EngineContextLocal.java | 76 ++++++ .../enginecontext/EngineContextManager.java | 44 ++++ .../EngineContextSelenium.java | 76 +++--- .../able/enginecontext/IEngineContext.java | 30 +++ .../com/ibm/able/report/ACReporterJSON.java | 46 ++++ .../com/ibm/able/report/CompressedReport.java | 133 +++++++++++ .../java/com/ibm/able/report/IReporter.java | 13 ++ .../com/ibm/able/report/ReporterFile.java | 12 + .../com/ibm/able/report/ReporterManager.java | 219 ++++++++++++++++++ .../com/ibm/able/report/ReporterStored.java | 15 ++ .../src/main/java/com/ibm/able/util/Misc.java | 12 + 26 files changed, 1168 insertions(+), 86 deletions(-) create mode 100644 java-accessibility-checker/lib/.gitignore rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{IEngineContext.java => abs/IAbstractAPI.java} (81%) create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Bounds.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Guideline.java rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{EngineContextManager.java => engine/eRuleConfidence.java} (60%) create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/eRuleLevel.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{selenium => enginecontext}/EngineContextSelenium.java (77%) create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java diff --git a/java-accessibility-checker/lib/.gitignore b/java-accessibility-checker/lib/.gitignore new file mode 100644 index 000000000..872aa273a --- /dev/null +++ b/java-accessibility-checker/lib/.gitignore @@ -0,0 +1 @@ +results \ No newline at end of file diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 990aeaf0b..8078eaf36 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -28,6 +28,8 @@ dependencies { // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java implementation 'org.seleniumhq.selenium:selenium-java:4.16.1' implementation 'com.google.code.gson:gson:2.11.0' + // https://mavenlibs.com/maven/dependency/org.mozilla/rhino + implementation 'org.mozilla:rhino:1.7.14' } // Apply a specific Java toolchain to ease working on different environments. diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java index 422366a54..ab3b746ff 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java @@ -16,11 +16,24 @@ package com.ibm.able; import java.io.IOException; +import java.util.Date; + import com.ibm.able.config.ACConfigManager; import com.ibm.able.config.Config; +import com.ibm.able.config.ConfigInternal; +import com.ibm.able.engine.ACEReport; import com.ibm.able.engine.ACReport; +import com.ibm.able.enginecontext.EngineContextManager; +import com.ibm.able.enginecontext.IEngineContext; +import com.ibm.able.report.ReporterManager; +import com.ibm.able.abs.IAbstractAPI; +import com.ibm.able.abs.MyFS; public class AccessibilityChecker { + private static boolean initialized = false; + private static IAbstractAPI myFS = new MyFS(); + private static IEngineContext localEngine; + /** * This function is responsible performing a scan based on the context that is provided, following are * the supported context type: @@ -47,32 +60,30 @@ public static ACReport getCompliance(Object content, String label) { AccessibilityChecker.initialize(); IEngineContext engineContext = EngineContextManager.getEngineContext(content); - try { - engineContext.loadEngine(); - } catch (IOException e) { - System.err.println("aChecker: Unable to load engine due to IOException: "+e.toString()); - e.printStackTrace(); - } // Get the Data when the scan is started // Start time will be in milliseconds elapsed since 1 January 1970 00:00:00 UTC up until now. - return engineContext.getCompliance(label); + long startScan = new Date().getTime(); + ACEReport origReport = engineContext.getCompliance(label); + String url = engineContext.getUrl(); + String title = engineContext.getTitle(); + ACReport finalReport = ReporterManager.get().addEngineReport("Selenium", startScan, url, title, label, origReport); + return finalReport; } public static Config getConfig() { return ACConfigManager.getConfig(); } - public static Config getConfigUnsupported() { + public static ConfigInternal getConfigUnsupported() { return ACConfigManager.getConfigUnsupported(); } private static void initialize() { + if (initialized) return; + initialized = true; + localEngine = EngineContextManager.getEngineContext(null); // TODO: - // if (Config) return; - // Config = await ACConfigManager.getConfigUnsupported(); - // await ACEngineManager.loadEngineLocal(); - // let absAPI = new MyFS(); // let refactorMap : RefactorMap = {} // let rules = ACEngineManager.getRulesSync(); // for (const rule of rules) { @@ -82,7 +93,7 @@ private static void initialize() { // } // } // } - // ReporterManager.initialize(Config, absAPI, await ACEngineManager.getRulesets()); + ReporterManager.initialize(getConfigUnsupported(), myFS, localEngine.getGuidelines()); // BaselineManager.initialize(Config, absAPI, refactorMap); } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/IEngineContext.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/IAbstractAPI.java similarity index 81% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/IEngineContext.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/IAbstractAPI.java index 1ad11b3a7..021daab86 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/IEngineContext.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/IAbstractAPI.java @@ -13,14 +13,13 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able; +package com.ibm.able.abs; import java.io.IOException; import com.ibm.able.engine.ACReport; -public interface IEngineContext { - void loadEngine() throws IOException; - - ACReport getCompliance(String label); +public interface IAbstractAPI { + public ACReport loadBaseline(String scanLabel); + public void writeFile(String path, Object contents) throws IOException; } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java new file mode 100644 index 000000000..c0cc2c0cb --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java @@ -0,0 +1,54 @@ +package com.ibm.able.abs; + +import com.ibm.able.engine.ACReport; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.google.gson.Gson; +import com.google.gson.stream.JsonReader; +import com.ibm.able.config.ACConfigManager; +import com.ibm.able.config.ConfigInternal; + +public class MyFS implements IAbstractAPI { + public static Gson gson = new Gson(); + + @Override + public void writeFile(String filePath, Object contents) throws IOException { + File outFile = this.prepFileSync(filePath); + FileWriter myWriter = new FileWriter(outFile); + myWriter.write(contents.toString()); + myWriter.close(); + } + + private File prepFileSync(String filePath) { + ConfigInternal config = ACConfigManager.getConfigUnsupported(); + Path outFile = Paths.get(System.getProperty("user.dir"), config.outputFolder, filePath); + File f = outFile.toFile(); + File dir = f.getParentFile(); + if (!dir.exists()) { + dir.mkdirs(); + } + return f; + } + + @Override + public ACReport loadBaseline(String scanLabel) { + ConfigInternal config = ACConfigManager.getConfigUnsupported(); + Path outPath = Paths.get(System.getProperty("user.dir"), config.baselineFolder, scanLabel+".json"); + File outFile = outPath.toFile(); + if (!outFile.exists()) return null; + JsonReader reader; + try { + reader = new JsonReader(new FileReader(outFile)); + } catch (FileNotFoundException e) { + return null; + } + return gson.fromJson(reader, ACReport.class); + } +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java index 10553a960..159f9e334 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java @@ -107,4 +107,9 @@ public class Config { * Default: ["html", "htm", "svg"] */ public String[] extensions = { "html", "htm", "svg" }; + + /** + * (optional) If the tool allows, should we capture screenshots + */ + public Boolean captureScreenshots = false; } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java index 3b4f9af00..c72421e8e 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java @@ -62,11 +62,6 @@ public class ConfigInternal extends Config { */ public String ruleArchiveVersion = null; - /** - * (optional) If the tool allows, should we capture screenshots - */ - public Boolean captureScreenshots = false; - /** * (optional) If the tool allows, should we run headless */ diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java new file mode 100644 index 000000000..7752c72d7 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java @@ -0,0 +1,56 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ + +package com.ibm.able.engine; +import java.util.Map; + +public class ACEReport { + + public static class Result { + public Result() {} + public Result(Result o) { + apiArgs = o.apiArgs; + bounds = o.bounds; + category = o.category; + message = o.message; + messageArgs = o.messageArgs.clone(); + path = o.path; + reasonId = o.reasonId; + ruleId = o.ruleId; + ruleTime = o.ruleTime; + snippet = o.snippet; + value = o.value.clone(); + } + public Object[] apiArgs; + public Bounds bounds; + public String category; + public String message; + public String[] messageArgs; + public Map path; + public String reasonId; + public String ruleId; + public int ruleTime; + public String snippet; + public String[] value; + } + + public int numExecuted; + public int ruleTime; + public int totalTime; + public Map> nls; + public Result[] results; + public String screenshot=null; +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java index 0be8b61f1..a6eb1f063 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java @@ -1,3 +1,18 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ package com.ibm.able.engine; public class ACError extends Error { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java index 68b1494c9..bc76d7d67 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java @@ -15,33 +15,161 @@ *****************************************************************************/ package com.ibm.able.engine; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; +import java.util.Map.Entry; + +import com.ibm.able.config.ConfigInternal; public class ACReport { - public static class Bounds { - int top; - int left; - int height; - int width; + public static class SummaryCounts { + public int violation = 0; + public int potentialviolation = 0; + public int recommendation = 0; + public int potentialrecommendation = 0; + public int manual = 0; + public int pass = 0; + public int ignored = 0; + public int elements = 0; + public int elementsViolation = 0; + public int elementsViolationReview = 0; + } + public static class Summary { + public SummaryCounts counts = new SummaryCounts(); + public long scanTime = 0; + public String ruleArchive = ""; + public String[] policies = {}; + public String[] reportLevels = {}; + public long startScan = 0; + public String URL = ""; } + public static class Result extends ACEReport.Result { + public boolean ignored = false; + public String help = ""; + public eRuleLevel level; + + public Result() {} + public Result(ACEReport.Result engineResult) { + super(engineResult); + } + } + public Result[] results = new Result[0]; + public int numExecuted = 0; + public Map> nls = new HashMap<>(); + public Summary summary = new Summary(); + public String scanID = ""; + public String toolID = ""; + public String label = ""; + public String screenshot=null; + public int ruleTime = 0; + + public ACReport() {} + public ACReport(ConfigInternal config, ACEReport engineReport, String label) { + numExecuted = engineReport.numExecuted; + nls = engineReport.nls; + screenshot = engineReport.screenshot; + ruleTime = engineReport.ruleTime; + results = new Result[engineReport.results.length]; + for (int idx=0; idx < results.length; ++idx) { + results[idx] = new Result(engineReport.results[idx]); + } + scanID = config.scanID; + toolID = config.toolID; + this.label = label; + } + + public void updateSummaryCounts() { + SummaryCounts counts = summary.counts; + counts.violation = 0; + counts.potentialviolation = 0; + counts.recommendation = 0; + counts.potentialrecommendation = 0; + counts.manual = 0; + counts.pass = 0; + counts.ignored = 0; + counts.elements = 0; + counts.elementsViolation = 0; + counts.elementsViolationReview = 0; + Set elementSet = new HashSet<>(); + Set elementViolationSet = new HashSet<>(); + Set elementViolationReviewSet = new HashSet<>(); + for (Result issue: results) { + elementSet.add(issue.path.get("dom")); + if (issue.ignored) { + ++counts.ignored; + } else { + if (eRuleLevel.violation.equals(issue.level)) { + ++counts.violation; + } else if (eRuleLevel.potentialviolation.equals(issue.level)) { + ++counts.potentialviolation; + } else if (eRuleLevel.recommendation.equals(issue.level)) { + ++counts.recommendation; + } else if (eRuleLevel.potentialrecommendation.equals(issue.level)) { + ++counts.potentialrecommendation; + } else if (eRuleLevel.manual.equals(issue.level)) { + ++counts.manual; + } else if (eRuleLevel.pass.equals(issue.level)) { + ++counts.pass; + } else if (eRuleLevel.ignored.equals(issue.level)) { + ++counts.ignored; + } + if (eRuleLevel.violation.equals(issue.level)) { + elementViolationSet.add(issue.path.get("dom")); + elementViolationReviewSet.add(issue.path.get("dom")); + } else if (eRuleLevel.potentialviolation.equals(issue.level) || eRuleLevel.manual.equals(issue.level)) { + elementViolationReviewSet.add(issue.path.get("dom")); + } + } + } + counts.elements = elementSet.size(); + counts.elementsViolation = elementViolationSet.size(); + counts.elementsViolationReview = elementViolationReviewSet.size(); + } + + public void filter(String[] reportLevels) { + Map> keepNlsKeys = new HashMap<>(); + List reportLevelsList = Arrays.asList(reportLevels); + Stream filtResults = Arrays.stream(results).filter(pageResult -> { + if (reportLevelsList.contains(pageResult.level.toString())) { + Set keepRuleReasons = keepNlsKeys.get(pageResult.ruleId); + if (keepRuleReasons == null) { + keepNlsKeys.put(pageResult.ruleId, new HashSet()); + keepRuleReasons = keepNlsKeys.get(pageResult.ruleId); + keepRuleReasons.add("0"); + } + keepRuleReasons.add(pageResult.reasonId); + if (pageResult.message.length() > 32000) { + pageResult.message = pageResult.message.substring(0, 32000 - 3) + "..."; + } + if (pageResult.snippet.length() > 32000) { + pageResult.snippet = pageResult.snippet.substring(0, 32000 - 3) + "..."; + } + return true; + } else { + return false; + } + }); + results = filtResults.toArray(size -> new Result[size]); - public static class Result { - public Object[] apiArgs; - public Bounds bounds; - public String category; - public String message; - public String[] messageArgs; - public Map path; - public String reasonId; - public String ruleId; - public int ruleTime; - public String snippet; - public String[] value; + if (nls != null) { + for (String ruleId: nls.keySet().toArray(new String[] {})) { + if (!keepNlsKeys.containsKey(ruleId)) { + nls.remove(ruleId); + } else { + Set keepRuleReasons = keepNlsKeys.get(ruleId); + Map nlsRuleMap = nls.get(ruleId); + for (String reasonId: nls.get(ruleId).values()) { + if (!keepRuleReasons.contains(reasonId)) { + nlsRuleMap.remove(reasonId); + } + } + } + } + } } - - public int numExecuted; - public int ruleTime; - public int totalTime; - public Map> nls; - public Result[] results; } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java new file mode 100644 index 000000000..5bc97b4f3 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java @@ -0,0 +1,86 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ + +package com.ibm.able.engine; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import com.ibm.able.config.ConfigInternal; +import com.ibm.able.report.CompressedReport; +import com.ibm.able.report.ReporterStored; + +public class ACReportSummary { + public static class SummaryCounts { + public int violation = 0; + public int potentialviolation = 0; + public int recommendation = 0; + public int potentialrecommendation = 0; + public int manual = 0; + public int pass = 0; + public int ignored = 0; + public int elements = 0; + public int elementsViolation = 0; + public int elementsViolationReview = 0; + } + public static class PageSummary { + public String label; + public ACReport.SummaryCounts counts; + } + public SummaryCounts counts = new SummaryCounts(); + + public long startReport = 0; + public long endReport = 0; + public String toolID = ""; + public String[] policies = {}; + public String[] reportLevels = {}; + public String[] labels = {}; + public String[] failLevels = {}; + public String scanID = ""; + public PageSummary[] pageScanSummery = new PageSummary[0]; + + public ACReportSummary() {} + public ACReportSummary(ConfigInternal config, long endReport, CompressedReport[] compressedReports) { + this.startReport = compressedReports[0].getStartScan(); + this.endReport = endReport; + this.toolID = config.toolID; + this.policies = config.policies; + this.reportLevels = config.reportLevels; + this.labels = config.label; + this.failLevels = config.failLevels; + this.scanID = config.scanID; + this.pageScanSummery = new PageSummary[compressedReports.length]; + for (int idx=0; idx", 1, null); + } + + @Override + public ACEReport getCompliance(String label) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getCompliance'"); + } + + @Override + public String getUrl() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getUrl'"); + } + + @Override + public String getTitle() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getTitle'"); + } + + @Override + public Guideline[] getGuidelines() { + String scriptStr = "JSON.stringify(new ace.Checker().getGuidelines())"; + String jsonGuidelines = engine.evaluateString(engineScope, scriptStr, "", 1, null).toString(); + return gson.fromJson(jsonGuidelines, Guideline[].class); + } + +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java new file mode 100644 index 000000000..3a2188a1a --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java @@ -0,0 +1,44 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.enginecontext; + +import java.io.IOException; + +import org.openqa.selenium.WebDriver; + +import com.ibm.able.util.Misc; + +public class EngineContextManager { + private EngineContextManager() {} + + public static IEngineContext getEngineContext(Object contentContext) { + IEngineContext engineContext = null; + if (contentContext == null) { + engineContext = new EngineContextLocal(); + } else if (Misc.classIsAvailable("org.openqa.selenium.WebDriver") && contentContext instanceof org.openqa.selenium.WebDriver) { + engineContext = new EngineContextSelenium((WebDriver) contentContext); + } + if (engineContext != null) { + try { + engineContext.loadEngine(); + } catch (IOException e) { + System.err.println("aChecker: Unable to load engine due to IOException: "+e.toString()); + e.printStackTrace(); + } + } + return engineContext; + } +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/selenium/EngineContextSelenium.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java similarity index 77% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/selenium/EngineContextSelenium.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java index 0030c94ff..bc8f58949 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/selenium/EngineContextSelenium.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java @@ -13,25 +13,28 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.selenium; +package com.ibm.able.enginecontext; import java.io.IOException; import java.time.Duration; import java.util.Date; import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import com.google.gson.Gson; -import com.ibm.able.IEngineContext; import com.ibm.able.config.ACConfigManager; import com.ibm.able.config.Config; import com.ibm.able.config.ConfigInternal; import com.ibm.able.engine.ACError; -import com.ibm.able.engine.ACReport; +import com.ibm.able.engine.Guideline; +import com.ibm.able.engine.ACEReport; import com.ibm.able.util.Fetch; public class EngineContextSelenium implements IEngineContext { + private static Gson gson = new Gson(); private WebDriver driver = null; private String engineContent = null; @@ -39,6 +42,7 @@ public EngineContextSelenium(WebDriver driver) { this.driver = driver; } + @Override public void loadEngine() throws IOException { ConfigInternal config = ACConfigManager.getConfigUnsupported(); String engineLoadMode = config.engineMode; @@ -85,7 +89,6 @@ public void loadEngine() throws IOException { } """, config.rulePack); } else if ("INJECT".equals(engineLoadMode)) { - Gson gson = new Gson(); // Selenium scriptStr = String.format(""" let cb = arguments[arguments.length - 1]; @@ -117,20 +120,16 @@ public void loadEngine() throws IOException { this.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(60)); - Object result = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr); - if (result != null) { - System.err.println(result); - } + ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr); } catch (Error e) { System.err.println(e); } } - public ACReport getCompliance(String label) { + @Override + public ACEReport getCompliance(String label) { Config config = ACConfigManager.getConfig(); - Gson gson = new Gson(); try { - Date startScan = new Date(); String scriptStr = String.format(""" let cb = arguments[arguments.length - 1]; try { @@ -154,10 +153,11 @@ public ACReport getCompliance(String label) { this.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(60)); String jsonReport = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr).toString(); + ACEReport report; if (!jsonReport.startsWith("{\"results\":[")) { throw new ACError(jsonReport); } else { - return gson.fromJson(jsonReport, ACReport.class); + report = gson.fromJson(jsonReport, ACEReport.class); } // TODO: // String getPolicies = "return new window.ace_ibma.Checker().rulesetIds;"; @@ -167,27 +167,45 @@ public ACReport getCompliance(String label) { // areValidPolicy(valPolicies, curPol); // } - // // If there is something to report... - // let finalReport : IBaselineReport; - // if (report.results) { - // // Add URL to the result object - // const url = await browser.getCurrentUrl(); - // const title = await browser.getTitle(); - // let origReport : IEngineReport = JSON.parse(JSON.stringify(report)); - // if (Config.captureScreenshots && browser.takeScreenshot) { - // const image = await browser.takeScreenshot(); - // origReport.screenshot = image; - // } - // finalReport = ReporterManager.addEngineReport("Selenium", startScan, url, title, label, origReport); - // } - // return { - // "report": finalReport, - // "webdriver": parsed - // } + // If there is something to report... + if (report.results != null) { + if (config.captureScreenshots) { + String image = ((TakesScreenshot)this.driver).getScreenshotAs(OutputType.BASE64); + report.screenshot = image; + } + } + return report; } catch (Error err) { System.err.println(err); throw err; } } + @Override + public String getUrl() { + return this.driver.getCurrentUrl(); + } + + @Override + public String getTitle() { + return this.driver.getTitle(); + } + + @Override + public Guideline[] getGuidelines() { + String scriptStr = String.format(""" +let cb = arguments[arguments.length - 1]; +try { + let checker = new window.ace_ibma.Checker(); + let customRulesets = []; + customRulesets.forEach((rs) => checker.addRuleset(rs)); + cb(JSON.stringify(checker.getGuidelines())); +} catch (e) { + cb(e); +} +"""); + String jsonGuidelines = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr).toString(); + return gson.fromJson(jsonGuidelines, Guideline[].class); + } + } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java new file mode 100644 index 000000000..4f456dbc2 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java @@ -0,0 +1,30 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.enginecontext; + +import java.io.IOException; + +import com.ibm.able.engine.ACEReport; +import com.ibm.able.engine.Guideline; + +public interface IEngineContext { + public void loadEngine() throws IOException; + + public ACEReport getCompliance(String label); + public String getUrl(); + public String getTitle(); + public Guideline[] getGuidelines(); +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java new file mode 100644 index 000000000..b287a62dd --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java @@ -0,0 +1,46 @@ +package com.ibm.able.report; + +import java.util.Date; + +import com.google.gson.Gson; +import com.ibm.able.config.ConfigInternal; +import com.ibm.able.engine.ACReport; +import com.ibm.able.engine.ACReportSummary; +import com.ibm.able.engine.Guideline; +import com.ibm.able.util.Misc; + +public class ACReporterJSON implements IReporter { + private static Gson gson = new Gson(); + + @Override + public String name() { + return "json"; + } + + @Override + public ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, ReporterStored storedReport) { + ACReport outReport = storedReport.engineReport; + return new ReporterFile( + outReport.label.replaceAll("[:?&=]", "_")+".json", + gson.toJson(outReport) + ); + } + + @Override + public ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, int endReport, + CompressedReport[] compressedReports) + { + if (compressedReports != null && compressedReports.length > 0) { + ACReportSummary summReport = new ACReportSummary(config, endReport, compressedReports); + if (summReport != null) { + Date startScan = new Date(compressedReports[0].getStartScan()); + String reportFilename = "summary_"+Misc.toISOString(startScan).replaceAll(":","-")+".json"; + if (!config.outputFilenameTimestamp) { + reportFilename = "summary.json"; + } + return new ReporterFile(reportFilename, gson.toJson(summReport)); + } + } + return null; + } +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java new file mode 100644 index 000000000..371533e96 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java @@ -0,0 +1,133 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.report; + +import java.util.HashMap; +import java.util.Map; + +import com.ibm.able.engine.ACReport; + +public class CompressedReport { + public static String scanID; + public static String toolID; + public static Map> nlsStore = new HashMap<>(); + + public Object[] data = {}; + + public CompressedReport(ReporterStored info) { + ACReport report = info.engineReport; + ACReport.Summary summary = report.summary; + CompressedReport.scanID = report.scanID; + CompressedReport.toolID = report.toolID; + this.data = new Object[] { + summary.startScan, // startScan (0) + summary.URL, // url (1) + info.pageTitle, // pagetitle (2) + report.label, // label (3) + info.scanProfile, // scanProfile (4) + report.numExecuted, // numExecuted (5) + summary.scanTime, // scanTime (6) + summary.ruleArchive, // ruleArchive (7) + summary.policies, // policies (8) + summary.reportLevels, // reportLevels (9) + new Object[report.results.length][] // (10) + }; + for (int idx=0; idx 32000) { + issue[idx2] = ((String) issue[idx2]).substring(0, 32000 - 3) + "..."; + } + } + Map storeRuleMap = nlsStore.getOrDefault(result.ruleId, new HashMap()); + storeRuleMap.put( + result.reasonId, + report.nls.getOrDefault( + result.ruleId, + new HashMap() + ).getOrDefault( + result.reasonId, + result.ruleId+"_"+result.reasonId + ) + ); + } + } + + public ReporterStored uncompress() { + ACReport engineReport = new ACReport(); + engineReport.label = (String)data[3]; + engineReport.numExecuted = (Integer)data[5]; + ACReport.Summary summary = engineReport.summary; + summary.scanTime = (Long)data[6]; + summary.ruleArchive = (String)data[7]; + summary.policies = (String[])data[8]; + summary.reportLevels = (String[])data[9]; + summary.startScan = (Long)data[0]; + summary.URL = (String)data[1]; + engineReport.results = new ACReport.Result[((Object[])data[10]).length]; + for (int idx=0; idx<((Object[][])data[10]).length; ++idx) { + Object[] issue = ((Object[][])data[10])[idx]; + ACReport.Result result = engineReport.results[idx] = new ACReport.Result(); + result.category = (String)issue[0]; + result.ruleId = (String)issue[1]; + result.value = (String[])issue[2]; + result.reasonId = (String)issue[3]; + result.messageArgs = (String[])issue[4]; + result.apiArgs = new Object[] {}; + result.path = (Map)issue[5]; + result.ruleTime = (Integer)issue[6]; + result.message = (String)issue[10]; + result.snippet = (String)issue[7]; + result.help = (String)issue[8]; + result.ignored = (Boolean)issue[9]; + result.level = ReporterManager.valueToLevel((String[])issue[2]); + Map nlsRuleMap = engineReport.nls.getOrDefault(result.ruleId, new HashMap()); + nlsRuleMap.put( + result.reasonId, + nlsStore.getOrDefault( + result.ruleId, + new HashMap() + ).getOrDefault( + result.reasonId, + result.ruleId+"_"+result.reasonId + ) + ); + } + engineReport.updateSummaryCounts(); + return new ReporterStored(data[2].toString(), data[4].toString(), null); + } + + public long getStartScan() { + return (Long)data[0]; + } + + public String getLabel() { + return (String)data[3]; + } +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java new file mode 100644 index 000000000..2b948c421 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java @@ -0,0 +1,13 @@ +package com.ibm.able.report; + +import com.ibm.able.config.ConfigInternal; +import com.ibm.able.engine.Guideline; + +public interface IReporter { + String name(); + /** + * @return [ reportPath: string, report: string ] + */ + ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, ReporterStored reportData); + ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, int endReport, CompressedReport[] summaryData); +}; \ No newline at end of file diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java new file mode 100644 index 000000000..aeeec3c03 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java @@ -0,0 +1,12 @@ +package com.ibm.able.report; + +public class ReporterFile { + public String path; + // summary: string | Buffer | ((filename?: string) => Promise) + public Object contents; + + public ReporterFile(String path, String contents) { + this.path = path; + this.contents = contents; + } +} \ No newline at end of file diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java new file mode 100644 index 000000000..0eee9db70 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java @@ -0,0 +1,219 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.report; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.gson.Gson; +import com.ibm.able.abs.IAbstractAPI; +import com.ibm.able.config.ConfigInternal; +import com.ibm.able.engine.ACEReport; +import com.ibm.able.engine.ACError; +import com.ibm.able.engine.ACReport; +import com.ibm.able.engine.Guideline; +import com.ibm.able.engine.eRuleConfidence; +import com.ibm.able.engine.eRuleLevel; +import com.ibm.able.engine.ACReport.Result; + +public class ReporterManager { + private static Gson gson = new Gson(); + private static ReporterManager singleton = null; + public static ReporterManager get() { + if (singleton == null) throw new ACError("RepoterManager not intialized"); + return singleton; + } + public static ReporterManager initialize(ConfigInternal config, IAbstractAPI absAPI, Guideline[] rulesets) { + return singleton = new ReporterManager(config, absAPI, rulesets); + } + + private ConfigInternal config; + private IAbstractAPI absAPI; + private Guideline[] rulesets; + private List reporters = new ArrayList<>(); + private List reports = new ArrayList<>(); + private IReporter returnReporter = new ACReporterJSON(); + + + private ReporterManager(ConfigInternal config, IAbstractAPI absAPI, Guideline[] rulesets) { + this.config = config; + this.absAPI = absAPI; + this.rulesets = rulesets; + if (config.perfMetrics) { + // TODO: + // reporters.add(new ACReporterMetrics(config.toolName, config.policies)); + } + + if (!Arrays.asList(config.outputFormat).contains("disable")) { + if (Arrays.asList(config.outputFormat).contains("json")) { + reporters.add(new ACReporterJSON()); + } + if (Arrays.asList(config.outputFormat).contains("html")) { + // TODO: + // reporters.push(new ACReporterHTML()) + } + if (Arrays.asList(config.outputFormat).contains("csv")) { + // TODO: + // reporters.add(new ACReporterCSV()); + } + if (Arrays.asList(config.outputFormat).contains("xlsx")) { + // TODO: + // reporters.add(new ACReporterXLSX()); + } + } + } + private Set usedLabels = new HashSet(); + + public ACReport addEngineReport(String scanProfile, long startScan, String url, String pageTitle, String label, ACEReport engineReport) { + verifyLabel(label); + usedLabels.add(label); + ACReport filteredReport = filterReport(engineReport, label); + filteredReport.summary.startScan = startScan; + filteredReport.summary.URL = url; + filteredReport.label = label; + ReporterStored storedReport = new ReporterStored(pageTitle, scanProfile, filteredReport); + for (Result issue: filteredReport.results) { + issue.help = getHelpUrl(issue); + } + CompressedReport compressedReport = new CompressedReport(storedReport); + if (reporters.size() > 0) { + reports.add(compressedReport); + for (IReporter reporter: reporters) { + ReporterFile reportInfo = reporter.generateReport(config, rulesets, storedReport); + if (reportInfo != null) { + try { + absAPI.writeFile(reportInfo.path, reportInfo.contents); + } catch (IOException e) { + System.err.println(e); + e.printStackTrace(); + } + } + } + } + ReporterFile retVal = returnReporter.generateReport(config, rulesets, storedReport); + if (retVal != null) return gson.fromJson(retVal.contents.toString(), ACReport.class); + return null; + } + + private void verifyLabel(String label) { + // In the case that the label is null or undefined, throw an error + if (label == null) { + throw new ACError("labelNotProvided: Label must be provided when calling aChecker.getCompliance."); + } + + // Check to make sure that the label that is provided is unique with all the other ones + // that we have gone through. + boolean labelUnique = isLabelUnique(label); + + // In the case that the label is not unique + if (!labelUnique) { + throw new ACError("Label provided to aChecker.getCompliance ("+label+") should be unique across all testcases in a single accessibility-checker session."); + } + } + + private boolean isLabelUnique(String label) { + return !usedLabels.contains(label); + } + + private ACReport filterReport(ACEReport engineResult, String scanLabel) { + Map>> ignoreLookup = new HashMap>> (); + + ACReport baselineReport = absAPI.loadBaseline(scanLabel); + if (baselineReport != null) { + for (Result issue : baselineReport.results) { + // ignoreLookup[issue.path.dom] = ignoreLookup[issue.path.dom] || {} + Map> a = ignoreLookup.get(issue.path.get("dom")); + if (a == null) { + ignoreLookup.put(issue.path.get("dom"), new HashMap>()); + a = ignoreLookup.get(issue.path.get("dom")); + } + // ignoreLookup[issue.path.dom][issue.ruleId] = ignoreLookup[issue.path.dom][issue.ruleId] || {} + Set b = a.get(issue.ruleId); + if (b == null) { + b = new HashSet(); + } + // ignoreLookup[issue.path.dom][issue.ruleId][issue.reasonId] = true; + b.add(issue.reasonId); + } + } + ACReport retVal = new ACReport(config, engineResult, scanLabel); + + // Set the config level and filter the results. Make note of which NLS keys we need + for (ACReport.Result pageResult: retVal.results) { + eRuleLevel reportLevel = ReporterManager.valueToLevel(pageResult.value); + boolean ignored = false; + if (!eRuleConfidence.PASS.toString().equals(pageResult.value[1]) + && ignoreLookup.containsKey(pageResult.path.get("dom")) + && ignoreLookup.get(pageResult.path.get("dom")).containsKey(pageResult.ruleId) + && ignoreLookup.get(pageResult.path.get("dom")).get(pageResult.ruleId).contains(pageResult.reasonId)) + { + ignored = true; + } + pageResult.ignored = ignored; + pageResult.level = reportLevel; + } + + retVal.updateSummaryCounts(); + retVal.filter(config.reportLevels); + + return retVal; + } + + public static eRuleLevel valueToLevel(String[] reportValue) { + eRuleLevel reportLevel = eRuleLevel.undefined; + if ("PASS".equals(reportValue[1])) { + reportLevel = eRuleLevel.pass; + } else if (("VIOLATION".equals(reportValue[0]) || "RECOMMENDATION".equals(reportValue[0])) && "MANUAL".equals(reportValue[1])) { + reportLevel = eRuleLevel.manual; + } else if ("VIOLATION".equals(reportValue[0])) { + if ("FAIL".equals(reportValue[1])) { + reportLevel = eRuleLevel.violation; + } else if ("POTENTIAL".equals(reportValue[1])) { + reportLevel = eRuleLevel.potentialviolation; + } + } else if ("RECOMMENDATION".equals(reportValue[0])) { + if ("FAIL".equals(reportValue[1])) { + reportLevel = eRuleLevel.recommendation; + } else if ("POTENTIAL".equals(reportValue[1])) { + reportLevel = eRuleLevel.potentialrecommendation; + } + } + return reportLevel; + } + + private String getHelpUrl(ACReport.Result issue) { + if (issue.help != null && issue.help.length() > 0) return issue.help; + return ""; + // TODO: + // let config = ReporterManager.config; + // let helpUrl = ReporterManager.absAPI.getChecker().engine.getHelp(issue.ruleId, issue.reasonId, !config.ruleArchivePath ? config.ruleArchive : config.ruleArchivePath.substring(config.ruleArchivePath.lastIndexOf("/")+1)); + // let minIssue = { + // message: issue.message, + // snippet: issue.snippet, + // value: issue.value, + // reasonId: issue.reasonId, + // ruleId: issue.ruleId, + // msgArgs: issue.messageArgs + // }; + // return `${helpUrl}#${encodeURIComponent(JSON.stringify(minIssue))}` + } +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java new file mode 100644 index 000000000..cf41153a8 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java @@ -0,0 +1,15 @@ +package com.ibm.able.report; + +import com.ibm.able.engine.ACReport; + +public class ReporterStored { + public String pageTitle; + public String scanProfile; + public ACReport engineReport; + + public ReporterStored(String title, String profile, ACReport report) { + pageTitle = title; + scanProfile = profile; + engineReport = report; + } +}; \ No newline at end of file diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java index 8d6365617..e8b59a7ff 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java @@ -15,6 +15,11 @@ *****************************************************************************/ package com.ibm.able.util; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + public class Misc { private Misc() {} @@ -34,4 +39,11 @@ public static boolean classIsAvailable(String className) { return false; } } + + public static String toISOString(Date d) { + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"); + df.setTimeZone(tz); + return df.format(d); + } } From fc99aa04a4228d131cbdc314f2c36dcfd1a6ff64 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 9 Aug 2024 00:51:12 -0500 Subject: [PATCH 008/161] Baselines --- .../com/ibm/able/AccessibilityChecker.java | 249 +++++++------- .../com/ibm/able/config/ACConfigManager.java | 4 +- .../java/com/ibm/able/engine/ACEReport.java | 22 +- .../java/com/ibm/able/engine/ACReport.java | 61 +++- .../main/java/com/ibm/able/engine/Bounds.java | 19 +- .../main/java/com/ibm/able/engine/Rule.java | 23 ++ .../enginecontext/EngineContextLocal.java | 12 +- .../enginecontext/EngineContextSelenium.java | 15 + .../able/enginecontext/IEngineContext.java | 2 + .../com/ibm/able/report/BaselineManager.java | 308 ++++++++++++++++++ .../ibm/able/AccessibilityCheckerTest.java | 19 ++ .../com/ibm/able/engine/ACReportTest.java | 49 +++ .../java/com/ibm/able/util/FetchTest.java | 18 +- 13 files changed, 640 insertions(+), 161 deletions(-) create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Rule.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java create mode 100644 java-accessibility-checker/lib/src/test/java/com/ibm/able/engine/ACReportTest.java diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java index ab3b746ff..271791e54 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java @@ -15,17 +15,23 @@ *****************************************************************************/ package com.ibm.able; -import java.io.IOException; import java.util.Date; +import java.util.HashMap; +import java.util.Map; import com.ibm.able.config.ACConfigManager; import com.ibm.able.config.Config; import com.ibm.able.config.ConfigInternal; import com.ibm.able.engine.ACEReport; import com.ibm.able.engine.ACReport; +import com.ibm.able.engine.Guideline; +import com.ibm.able.engine.Rule; import com.ibm.able.enginecontext.EngineContextManager; import com.ibm.able.enginecontext.IEngineContext; +import com.ibm.able.report.BaselineManager; import com.ibm.able.report.ReporterManager; +import com.ibm.able.report.BaselineManager.DiffResult; +import com.ibm.able.report.BaselineManager.eAssertResult; import com.ibm.able.abs.IAbstractAPI; import com.ibm.able.abs.MyFS; @@ -83,37 +89,37 @@ private static void initialize() { if (initialized) return; initialized = true; localEngine = EngineContextManager.getEngineContext(null); - // TODO: - // let refactorMap : RefactorMap = {} - // let rules = ACEngineManager.getRulesSync(); - // for (const rule of rules) { - // if (rule.refactor) { - // for (const key in rule.refactor) { - // refactorMap[key] = rule; - // } - // } - // } - ReporterManager.initialize(getConfigUnsupported(), myFS, localEngine.getGuidelines()); - // BaselineManager.initialize(Config, absAPI, refactorMap); + Map refactorMap = new HashMap<>(); + Rule[] rules = localEngine.getRules(); + for (Rule rule: rules) { + if (rule.refactor != null) { + for (String key: rule.refactor.keySet()) { + refactorMap.put(key, rule); + } + } + } + ConfigInternal config = getConfigUnsupported(); + ReporterManager.initialize(config, myFS, localEngine.getGuidelines()); + BaselineManager.initialize(config, myFS, refactorMap); } -// /** -// * This function is responsible for comparing the scan results with baseline or checking that there are -// * no violations which fall into the failsLevels levels. In the case a baseline is found then baseline will -// * be used to perform the check, in the case no baseline is provided then we comply with only failing if -// * there is a sinble violation which falls into failLevels. -// * -// * @param {ReportResult} actual - the actual results object provided by the user, this object should follow the -// * same format as outlined in the return of aChecker.buildReport function. -// * -// * @return {int} - return 0 in the case actual matches baseline or no violations fall into failsLevels, -// * return 1 in the case actual results does not match baseline results, -// * return 2 in the case that there is a failure based on failLevels (this means no baseline found). -// * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. -// */ -// export function assertCompliance(report: IBaselineReport) : eAssertResult { -// return BaselineManager.assertCompliance(report) -// } + /** + * This function is responsible for comparing the scan results with baseline or checking that there are + * no violations which fall into the failsLevels levels. In the case a baseline is found then baseline will + * be used to perform the check, in the case no baseline is provided then we comply with only failing if + * there is a sinble violation which falls into failLevels. + * + * @param {ReportResult} actual - the actual results object provided by the user, this object should follow the + * same format as outlined in the return of aChecker.buildReport function. + * + * @return {int} - return 0 in the case actual matches baseline or no violations fall into failsLevels, + * return 1 in the case actual results does not match baseline results, + * return 2 in the case that there is a failure based on failLevels (this means no baseline found). + * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. + */ + public static eAssertResult assertCompliance(ACReport report) { + return BaselineManager.assertCompliance(report); + } // /** // * This function is responsible for printing the scan results to console. @@ -134,124 +140,87 @@ private static void initialize() { // return ACBrowserManager.close(); // } -// /** -// * This function is responsible for getting the diff results based on label for a scan that was already performed. -// * -// * @param {String} label - Provide a lable for which to get the diff results for. -// * -// * @return {Object} - return the diff results object from global space based on label provided, the object will be -// * in the same format as outlined in the return of aChecker.diffResultsWithExpected function. -// */ -// export function getDiffResults(label: string) { -// return BaselineManager.getDiffResults(label); -// } - -// /** -// * This function is responsible for getting the baseline object for a label that was provided. -// * -// * @param {String} label - Provide a lable for which to get the baseline for. -// * -// * @return {Object} - return the baseline object from global space based on label provided, the object will be -// * in the same format as outlined in the return of aChecker.buildReport function. -// */ -// export function getBaseline(label: string) { -// return BaselineManager.getBaseline(label); -// } + /** + * This function is responsible for getting the diff results based on label for a scan that was already performed. + * + * @param {String} label - Provide a lable for which to get the diff results for. + * + * @return {Object} - return the diff results object from global space based on label provided, the object will be + * in the same format as outlined in the return of aChecker.diffResultsWithExpected function. + */ + public static DiffResult[] getDiffResults(String label) { + return BaselineManager.getDiffResults(label); + } -// /** -// * This function is responsible for comparing actual with expected and returning all the differences as an array. -// * -// * @param {Object} actual - Provide the actual object to be used for compare -// * @param {Object} expected - Provide the expected object to be used for compare -// * @param {boolean} clean - Provide a boolean if both the actual and expected objects need to be cleaned -// * cleaning refers to converting the objects to match with a basic compliance -// * compare of xpath and ruleId. -// * -// * @return {Object} differences - return an array of diff objects that were found, following is the format of the object: -// * [ -// * { -// * "kind": "E", -// * "path": [ -// * "reports", -// * 0, -// * "issues", -// * 10, -// * "xpath" -// * ], -// * "lhs": "/html[1]/body[1]/div[2]/table[5]", -// * "rhs": "/html[1]/body[1]/div[2]/table[5]d", -// * }, -// * { -// * "kind": "E", -// * "path": [ -// * "label" -// * ], -// * "lhs": "Table-layoutMultiple", -// * "rhs": "dependencies/tools-rules-html/v2/a11y/test/g471/Table-layoutMultiple.html", -// * } -// * ] -// */ -// export function diffResultsWithExpected(actual, expected, clean) { -// return BaselineManager.diffResultsWithExpected(actual, expected, clean); -// } + /** + * This function is responsible for getting the baseline object for a label that was provided. + * + * @param {String} label - Provide a lable for which to get the baseline for. + * + * @return {Object} - return the baseline object from global space based on label provided, the object will be + * in the same format as outlined in the return of aChecker.buildReport function. + */ + public static ACReport getBaseline(String label) { + return BaselineManager.getBaseline(label); + } -// /** -// * This function is responsible for cleaning up the compliance baseline or actual results, based on -// * a pre-defined set of criterias, such as the following: -// * 1. No need to compare summary object -// * 2. Only need to compare the ruleId and xpath in for each of the issues -// * -// * @param {Object} objectToClean - Provide either an baseline or actual results object which would be in the -// * the same format as outlined in the return of aChecker.buildReport function. -// * -// * @return {Object} objectToClean - return an object that was cleaned to only contain the information that is -// * needed for compare. Following is a sample of how the cleaned object will look like: -// * { -// * "label": "unitTestContent", -// * "reports": [ -// * { -// * "frameIdx": "0", -// * "frameTitle": "Frame 0", -// * "issues": [ -// * { -// * "ruleId": "1", -// * "xpath": "/html[1]/head[1]/style[1]" -// * } -// * .... -// * ] -// * }, -// * { -// * "frameIdx": "1", -// * "frameTitle": "Frame 1", -// * "issues": [ -// * { -// * "ruleId": "471", -// * "xpath": "/html[1]/body[1]/div[2]/table[3]" -// * } -// * .... -// * ] -// * } -// * ] -// * } -// */ -// export function cleanComplianceObjectBeforeCompare(objectToClean) { -// return BaselineManager.cleanComplianceObjectBeforeCompare(objectToClean); -// } + /** + * This function is responsible for comparing actual with expected and returning all the differences as an array. + * + * @param {Object} actual - Provide the actual object to be used for compare + * @param {Object} expected - Provide the expected object to be used for compare + * @param {boolean} clean - Provide a boolean if both the actual and expected objects need to be cleaned + * cleaning refers to converting the objects to match with a basic compliance + * compare of xpath and ruleId. + * + * @return {Object} differences - return an array of diff objects that were found, following is the format of the object: + * [ + * { + * "kind": "E", + * "path": [ + * "reports", + * 0, + * "issues", + * 10, + * "xpath" + * ], + * "lhs": "/html[1]/body[1]/div[2]/table[5]", + * "rhs": "/html[1]/body[1]/div[2]/table[5]d", + * }, + * { + * "kind": "E", + * "path": [ + * "label" + * ], + * "lhs": "Table-layoutMultiple", + * "rhs": "dependencies/tools-rules-html/v2/a11y/test/g471/Table-layoutMultiple.html", + * } + * ] + */ + public static DiffResult[] diffResultsWithExpected(ACReport actual, ACReport expected) { + return BaselineManager.diffResultsWithExpected(actual, expected); + } // export function addRuleset(ruleset) { // ACEngineManager.addRuleset(ruleset); // } -// export async function getRuleset(rsId) { -// return ACEngineManager.getRuleset(rsId); -// }; + public static Guideline getGuideline(String rsId) { + Guideline[] gs = getGuidelines(); + for (int i=0; i { + int cc = b.category.compareTo(a.category); + if (cc != 0) return cc; + int pc = b.path.get("dom").compareTo(a.path.get("dom")); + if (pc != 0) return pc; + return b.ruleId.compareTo(a.ruleId); + }); + } + + @Override + public Object clone() { + // Shallow copy + ACReport ret = null; + try { + ret = (ACReport)super.clone(); + } catch (CloneNotSupportedException ex) { + System.err.println(ex); + throw new RuntimeException(); + } + ret.summary = (Summary)summary.clone(); + ret.results = new ACReport.Result[results.length]; + for (int idx=0; idx> refactor = null; +} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java index 2a0a9aca2..f3aed0446 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java @@ -21,6 +21,7 @@ import com.ibm.able.config.ConfigInternal; import com.ibm.able.engine.ACEReport; import com.ibm.able.engine.Guideline; +import com.ibm.able.engine.Rule; import com.ibm.able.util.Fetch; import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; @@ -33,7 +34,7 @@ public class EngineContextLocal implements IEngineContext { @Override public void loadEngine() throws IOException { ConfigInternal config = ACConfigManager.getConfigUnsupported(); - String engineContent = Fetch.get(config.rulePack+"/ace.js"); + String engineContent = Fetch.get(config.rulePack+"/ace.js")+";var ace_checker = new ace.Checker();"; // Creates and enters a Context. The Context stores information // about the execution environment of a script. @@ -68,9 +69,16 @@ public String getTitle() { @Override public Guideline[] getGuidelines() { - String scriptStr = "JSON.stringify(new ace.Checker().getGuidelines())"; + String scriptStr = "JSON.stringify(ace_checker.getGuidelines())"; String jsonGuidelines = engine.evaluateString(engineScope, scriptStr, "", 1, null).toString(); return gson.fromJson(jsonGuidelines, Guideline[].class); + } + + @Override + public Rule[] getRules() { + String scriptStr = "JSON.stringify(Object.keys(ace_checker.engine.ruleMap).map(key => ace_checker.engine.ruleMap[key]))"; + String jsonGuidelines = engine.evaluateString(engineScope, scriptStr, "", 1, null).toString(); + return gson.fromJson(jsonGuidelines, Rule[].class); } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java index bc8f58949..6a0cf0f8f 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java @@ -30,6 +30,7 @@ import com.ibm.able.config.ConfigInternal; import com.ibm.able.engine.ACError; import com.ibm.able.engine.Guideline; +import com.ibm.able.engine.Rule; import com.ibm.able.engine.ACEReport; import com.ibm.able.util.Fetch; @@ -208,4 +209,18 @@ public Guideline[] getGuidelines() { return gson.fromJson(jsonGuidelines, Guideline[].class); } + @Override + public Rule[] getRules() { + String scriptStr = String.format(""" +let cb = arguments[arguments.length - 1]; +try { + let checker = new window.ace_ibma.Checker(); + cb(JSON.stringify(checker.getRules())); +} catch (e) { + cb(e); +} +"""); + String jsonGuidelines = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr).toString(); + return gson.fromJson(jsonGuidelines, Rule[].class); + } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java index 4f456dbc2..9fb7e67f3 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java @@ -19,6 +19,7 @@ import com.ibm.able.engine.ACEReport; import com.ibm.able.engine.Guideline; +import com.ibm.able.engine.Rule; public interface IEngineContext { public void loadEngine() throws IOException; @@ -27,4 +28,5 @@ public interface IEngineContext { public String getUrl(); public String getTitle(); public Guideline[] getGuidelines(); + public Rule[] getRules(); } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java new file mode 100644 index 000000000..1415b92d0 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java @@ -0,0 +1,308 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*****************************************************************************/ + +package com.ibm.able.report; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +import com.google.gson.Gson; +import com.ibm.able.abs.IAbstractAPI; +import com.ibm.able.config.ConfigInternal; +import com.ibm.able.engine.ACReport; +import com.ibm.able.engine.ACReport.Result; +import com.ibm.able.engine.Rule; + +/** + * This interface is responsible for aChecker baselines and comparing scans to baselines + */ +public class BaselineManager { + private static Gson gson = new Gson(); + public static enum eAssertResult { + ERROR(-1), + PASS(0), + BASELINE_MISMATCH(1), + FAIL(2) + ; + + private final int val; + + eAssertResult(final int val) { + this.val = val; + } + + int intValue() { + return this.val; + } + } + + public static class DiffResult { + public String kind = null; + public Object[] path = new Object[]{}; + public Object lhs = null; + public Object rhs = null; + public Integer index = null; + public DiffResult item = null; + + public DiffResult(String kind, Object[] path, Object lhs, Object rhs) { + this.kind = kind; + this.path = path; + this.lhs = lhs; + this.rhs = rhs; + } + + public DiffResult(String kind, int index, Object lhs, Object rhs) { + this.kind = kind; + this.index = index; + if (lhs != null && rhs != null) throw new RuntimeException("Cannot have index with lhs and rhs"); + this.item = new DiffResult(lhs != null ? "D" : "N", null, lhs, rhs); + } + } + + private static ConfigInternal config; + private static Map diffResults = new HashMap<>(); + private static IAbstractAPI absAPI; + private static Map refactorMap; + + public static void initialize(ConfigInternal config, IAbstractAPI absAPI, Map refactorMap) { + BaselineManager.config = config; + BaselineManager.absAPI = absAPI; + BaselineManager.refactorMap = refactorMap; + } + + public static ACReport getBaseline(String label) { + try { + ACReport retVal = BaselineManager.absAPI.loadBaseline(label); + if (retVal != null && retVal.results != null) { + for (ACReport.Result result: retVal.results) { + if (refactorMap.containsKey(result.ruleId)) { + Rule rule = refactorMap.get(result.ruleId); + Map mapping = rule.refactor.get(result.ruleId); + result.ruleId = rule.id; + result.reasonId = mapping.get(result.reasonId); + } + } + } + return retVal; + } catch (Error e) { + // console.error("getBaseline Error:", e); + return null; + } + } + + /** + * This function is responsible for comparing the scan results with baseline or checking that there are + * no violations which fall into the failsLevels levels. In the case a baseline is found then baseline will + * be used to perform the check, in the case no baseline is provided then we comply with only failing if + * there is a sinble violation which falls into failLevels. + * + * @param {Object} actual - the actual results object provided by the user, this object should follow the + * same format as outlined in the return of aChecker.buildReport function. + * + * @return {int} - return 0 in the case actual matches baseline or no violations fall into failsLevels, + * return 1 in the case actual results does not match baseline results, + * return 2 in the case that there is a failure based on failLevels (this means no baseline found). + * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. + * + * PUBLIC API + * + * @memberOf this + */ + public static eAssertResult assertCompliance(ACReport actualResults) { + // Get the label directly from the results object, the same label has to match + // the baseline object which is available in the global space. + String label = actualResults.label; + + // Fetch the baseline object based on the label provided + ACReport expected = BaselineManager.getBaseline(label); + + // In the case there are no baseline found then run a different assertion algo, + // when there is baseline compare the baselines in the case there is no baseline then + // check to make sure there are no violations that are listed in the fails on. + if (expected != null) { + // Run the diff algo to get the list of differences + DiffResult[] differences = BaselineManager.diffResultsWithExpected(actualResults, expected); + + // console.log("difference=" + JSON.stringify(differences, null, ' ')); + + // In the case that there are no differences then that means it passed + if (differences == null || differences.length == 0) { + return eAssertResult.PASS; + } else { + // Re-sort results and check again + ACReport modActual = (ACReport) actualResults.clone(); + modActual.sortResults(); + ACReport modExpected = (ACReport) expected.clone(); + modExpected.sortResults(); + DiffResult[] differences2 = BaselineManager.diffResultsWithExpected(modActual, modExpected); + if (differences2 == null || differences2.length == 0) { + return eAssertResult.PASS; + } else { + // In the case that there are failures add the whole diff array to + // global space indexed by the label so that user can access it. + BaselineManager.diffResults.put(label, differences); + + return eAssertResult.BASELINE_MISMATCH; + } + } + } else { + // In the case that there was no baseline data found compare the results based on + // the failLevels array, which was defined by the user. + int returnCode = BaselineManager.compareBasedOnFailLevels(actualResults); + + // In the case there are no violations that match the fail on then return as success + if (returnCode == 0) { + return eAssertResult.PASS; + } else { + // In the case there are some violation that match in the fail on then return 2 + // to identify that there was a failure, and we used a 2nd method for compare. + return eAssertResult.FAIL; + } + } + }; + + + /** + * This function is responsible for comparing actual with expected and returning all the differences as an array. + * + * @param {Object} actual - Provide the actual object to be used for compare + * @param {Object} expected - Provide the expected object to be used for compare + * @param {boolean} clean - Provide a boolean if both the actual and expected objects need to be cleaned + * cleaning refers to converting the objects to match with a basic compliance + * compare of xpath and ruleId. + * + * @return {Object} differences - return an array of diff objects that were found, following is the format of the object: + * [ + * { + * "kind": "E", + * "path": [ + * "reports", + * 0, + * "issues", + * 10, + * "xpath" + * ], + * "lhs": "/html[1]/body[1]/div[2]/table[5]", + * "rhs": "/html[1]/body[1]/div[2]/table[5]d", + * }, + * { + * "kind": "E", + * "path": [ + * "label" + * ], + * "lhs": "Table-layoutMultiple", + * "rhs": "dependencies/tools-rules-html/v2/a11y/test/g471/Table-layoutMultiple.html", + * } + * ] + * + * PUBLIC API + * + * @memberOf this + */ + public static DiffResult[] diffResultsWithExpected(ACReport actual, ACReport expected) { + // Run Deep diff function to compare the actual and expected values. + DiffResult[] differences = diff(actual, expected); + if (differences != null && differences.length > 0) { + differences = Arrays.stream(differences).filter(difference -> { + return "E".equals(difference.kind) + && difference.path.length == 4 + && difference.path.length > 2 && "bounds".equals(difference.path[2]) + && Math.abs((Integer)difference.lhs-(Integer)difference.rhs) <= 1; + }).toArray(size -> new DiffResult[size]); + if (differences.length == 0) return null; + } + + // Return the results of the diff, which will include the differences between the objects + return differences; + } + + /** + * This function is responsible for checking if any of the issues reported have any level that falls + * into the failsLevel array. + * + * @param {Object} results - Provide the scan results, object which would be in the + * the same format as outlined in the return of aChecker.buildReport function. + * + * @return {int} - return 1 in the case a single issue was found which is in the failsLevel array. + * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. + * + * PRIVATE METHOD + * + * @memberOf this + */ + public static int compareBasedOnFailLevels(ACReport report) { + // Variable Declaration + String[] failLevels = BaselineManager.config.failLevels; + + // Loop over all the issues to check for any level that is in failLevels + // console.log(report); + for (ACReport.Result issue: report.results) { + // In the case current level is in the failsLevel array them fail, with out checking further + // currently we are not saving exactly which results failed, as all the issues are going to be saved to + // results file. + if (Arrays.asList(failLevels).indexOf(issue.level.toString()) > -1) { + // return 1 as there was a fialure + return 1; + } + } + + // return 0 as there were no levels that fall into the failLevels + return 0; + } + + /** + * This function is responsible for getting the diff results based on label for a scan that was already performed. + * + * @param {String} label - Provide a lable for which to get the diff results for. + * + * @return {Object} - return the diff results object from global space based on label provided, the object will be + * in the same format as outlined in the return of aChecker.diffResultsWithExpected function. + * + * PUBLIC API + * + * @memberOf this + */ + public static DiffResult[] getDiffResults(String label) { + return diffResults.get(label); + } + + private static DiffResult[] diff(ACReport actual, ACReport expected) { + Result[] actualRs = actual.results; + Result[] expectedRs = expected.results; + ArrayList retVal = new ArrayList<>(); + for (int idx=actualRs.length; idx < expectedRs.length; ++idx) { + retVal.add(new DiffResult("A", idx, null, gson.toJson(expectedRs[idx]))); + } + for (int idx=expectedRs.length; idx < actualRs.length; ++idx) { + retVal.add(new DiffResult("A", idx, gson.toJson(expectedRs[idx]), null)); + } + for (int idx=0; idx 0); } + + @Test public void baselines() throws IOException { + Paths.get("baselines", "getComplianceTest3.json").toFile().delete(); + AccessibilityCheckerTest.driver.get("https://altoromutual.12mc9fdq8fib.us-south.codeengine.appdomain.cloud/"); + ACReport report = AccessibilityChecker.getCompliance(driver, "getComplianceTest2"); + assertEquals(eAssertResult.FAIL, AccessibilityChecker.assertCompliance(report)); + new File("baselines").mkdirs(); + Files.copy(Paths.get("results", "getComplianceTest2.json").toFile(), Paths.get("baselines", "getComplianceTest3.json").toFile()); + + report = AccessibilityChecker.getCompliance(driver, "getComplianceTest3"); + assertEquals(eAssertResult.PASS, AccessibilityChecker.assertCompliance(report)); + Paths.get("baselines", "getComplianceTest3.json").toFile().delete(); + } } diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/engine/ACReportTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/engine/ACReportTest.java new file mode 100644 index 000000000..371a12422 --- /dev/null +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/engine/ACReportTest.java @@ -0,0 +1,49 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.engine; + +import org.junit.Test; +import static org.junit.Assert.*; + +import com.ibm.able.engine.ACReport; + +public class ACReportTest { + + @Test public void cloneTest() { + ACReport one = new ACReport(); + one.results = new ACReport.Result[1]; + one.results[0] = new ACReport.Result(); + ACReport two = (ACReport) one.clone(); + assertNotSame(one, two); + + two.label="ASDF"; + assertNotEquals(one.label, two.label); + + two.summary.URL="Hi"; + assertNotEquals(one.summary.URL, two.summary.URL); + + two.summary.counts.elements = 5; + assertNotEquals(one.summary.counts.elements, two.summary.counts.elements); + + assertNotSame(one.results[0], two.results[0]); + + two.results[0].category = "Test"; + assertNotEquals(one.results[0].category, two.results[0].category); + + two.results[0].bounds.top = 5; + assertNotEquals(one.results[0].bounds.top, two.results[0].bounds.top); + } +} diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java index 9cb22c9ee..3929d6e57 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java @@ -1,6 +1,18 @@ -/* - * This source file was generated by the Gradle 'init' task - */ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ package com.ibm.able.util; import org.junit.Test; From 603b3a0af9a2d030c3b6bfb6dc606b76c146b64b Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 9 Aug 2024 01:24:26 -0500 Subject: [PATCH 009/161] Scan summaries --- .../com/ibm/able/AccessibilityChecker.java | 8 +++++--- .../com/ibm/able/engine/ACReportSummary.java | 9 +++++---- .../com/ibm/able/report/ACReporterJSON.java | 5 +++-- .../com/ibm/able/report/CompressedReport.java | 2 +- .../java/com/ibm/able/report/IReporter.java | 2 +- .../com/ibm/able/report/ReporterManager.java | 20 ++++++++++++++++++- .../ibm/able/AccessibilityCheckerTest.java | 1 + 7 files changed, 35 insertions(+), 12 deletions(-) diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java index 271791e54..6343f976b 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java @@ -101,6 +101,8 @@ private static void initialize() { ConfigInternal config = getConfigUnsupported(); ReporterManager.initialize(config, myFS, localEngine.getGuidelines()); BaselineManager.initialize(config, myFS, refactorMap); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> AccessibilityChecker.close() )); } /** @@ -136,9 +138,9 @@ public static eAssertResult assertCompliance(ACReport report) { // return ReporterManager.stringifyResults(report) // } -// export function close() { -// return ACBrowserManager.close(); -// } + public static void close() { + ReporterManager.get().generateSummaries(); + } /** * This function is responsible for getting the diff results based on label for a scan that was already performed. diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java index 5bc97b4f3..18ac21235 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java @@ -53,7 +53,7 @@ public static class PageSummary { public String[] labels = {}; public String[] failLevels = {}; public String scanID = ""; - public PageSummary[] pageScanSummery = new PageSummary[0]; + public PageSummary[] pageScanSummary = new PageSummary[0]; public ACReportSummary() {} public ACReportSummary(ConfigInternal config, long endReport, CompressedReport[] compressedReports) { @@ -65,11 +65,12 @@ public ACReportSummary(ConfigInternal config, long endReport, CompressedReport[] this.labels = config.label; this.failLevels = config.failLevels; this.scanID = config.scanID; - this.pageScanSummery = new PageSummary[compressedReports.length]; + this.pageScanSummary = new PageSummary[compressedReports.length]; for (int idx=0; idx 0) { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java index 371533e96..0c36b19a1 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java @@ -120,7 +120,7 @@ public ReporterStored uncompress() { ); } engineReport.updateSummaryCounts(); - return new ReporterStored(data[2].toString(), data[4].toString(), null); + return new ReporterStored(data[2].toString(), data[4].toString(), engineReport); } public long getStartScan() { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java index 2b948c421..24f28f17d 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java @@ -9,5 +9,5 @@ public interface IReporter { * @return [ reportPath: string, report: string ] */ ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, ReporterStored reportData); - ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, int endReport, CompressedReport[] summaryData); + ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, long endReport, CompressedReport[] summaryData); }; \ No newline at end of file diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java index 0eee9db70..c827fb3ce 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -53,7 +54,6 @@ public static ReporterManager initialize(ConfigInternal config, IAbstractAPI abs private List reports = new ArrayList<>(); private IReporter returnReporter = new ACReporterJSON(); - private ReporterManager(ConfigInternal config, IAbstractAPI absAPI, Guideline[] rulesets) { this.config = config; this.absAPI = absAPI; @@ -216,4 +216,22 @@ private String getHelpUrl(ACReport.Result issue) { // }; // return `${helpUrl}#${encodeURIComponent(JSON.stringify(minIssue))}` } + + public void generateSummaries() { + long endReport = new Date().getTime(); + // If no scans, don't generate summaries + if (reports.isEmpty()) return; + for (IReporter reporter: reporters) { + CompressedReport[] cReports = reports.toArray(new CompressedReport[reports.size()]); + ReporterFile summaryInfo = reporter.generateSummary(config, rulesets, endReport, cReports); + if (summaryInfo != null) { + try { + absAPI.writeFile(summaryInfo.path, summaryInfo.contents); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + reports.clear(); + } } diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index 167756c06..d062fda8c 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -48,6 +48,7 @@ public class AccessibilityCheckerTest { */ @AfterClass public static void teardown() { AccessibilityCheckerTest.driver.close(); + AccessibilityChecker.close(); } @Test public void getCompliance() { From 3cf03d4ca0cfcbf142ec1e7d9392b0c51364cff8 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 9 Aug 2024 08:53:04 -0500 Subject: [PATCH 010/161] Add jar build --- java-accessibility-checker/README-DEV.md | 21 +++++++++++++++++++++ java-accessibility-checker/lib/build.gradle | 16 ++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 java-accessibility-checker/README-DEV.md diff --git a/java-accessibility-checker/README-DEV.md b/java-accessibility-checker/README-DEV.md new file mode 100644 index 000000000..0432971e3 --- /dev/null +++ b/java-accessibility-checker/README-DEV.md @@ -0,0 +1,21 @@ +## Example gradle commands + +Run a specific testcase: +``` +./gradlew test --tests com.ibm.able.AccessibilityCheckerTest +``` + +Run all tests: +``` +./gradlew test +``` + +Create jar (result in lib/build/libs): +``` +./gradlew jar +``` + +Generate javadoc +``` +./gradlew javadoc +``` diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 8078eaf36..96d44cfdf 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -10,6 +10,10 @@ plugins { id 'java-library' } +group 'com.ibm.able' +version '1.0.0-beta-1' +archivesBaseName = 'accessibility-checker' + repositories { // Use Maven Central for resolving dependencies. mavenCentral() @@ -43,4 +47,16 @@ test { testLogging { showStandardStreams = true } +} + +jar { + // manifest { + // attributes "Main-Class": "com.baeldung.fatjar.Application" + // } + + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } + + duplicatesStrategy = DuplicatesStrategy.INCLUDE } \ No newline at end of file From 6ef30e8f00d561bed5fca3ef1c3a90ce4a4bcd18 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 15:27:40 -0500 Subject: [PATCH 011/161] Java test suite --- java-accessibility-checker/lib/build.gradle | 2 +- .../com/ibm/able/config/ACConfigManager.java | 5 +- .../enginecontext/EngineContextLocal.java | 2 +- .../enginecontext/EngineContextSelenium.java | 24 +-- .../com/ibm/able/report/ReporterManager.java | 2 +- .../main/java/com/ibm/able/util/Fetch.java | 63 +++++++- .../ibm/able/AccessibilityCheckerTest.java | 141 ++++++++++++++++++ 7 files changed, 220 insertions(+), 19 deletions(-) diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 96d44cfdf..109a47227 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -30,7 +30,7 @@ dependencies { implementation libs.guava // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java - implementation 'org.seleniumhq.selenium:selenium-java:4.16.1' + implementation 'org.seleniumhq.selenium:selenium-java:4.23.0' implementation 'com.google.code.gson:gson:2.11.0' // https://mavenlibs.com/maven/dependency/org.mozilla/rhino implementation 'org.mozilla:rhino:1.7.14' diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java index e4be11154..713870b1d 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java @@ -126,10 +126,7 @@ private static ConfigInternal processACConfig(ConfigInternal ACConfig) throws IO Archive[] ruleArchiveParse; try { - // if (ACConfig.ignoreHTTPSErrors) { - // process.env.NODE_TLS_REJECT_UNAUTHORIZED="0" - // } - ruleArchiveParse = Fetch.getJSONArr(ruleArchiveFile, Archive[].class); + ruleArchiveParse = Fetch.getJSONArr(ruleArchiveFile, Archive[].class, ACConfig.ignoreHTTPSErrors); } catch (Error err) { System.err.println(ruleArchiveFile); System.err.println(err.toString()); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java index f3aed0446..bb07b434c 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java @@ -34,7 +34,7 @@ public class EngineContextLocal implements IEngineContext { @Override public void loadEngine() throws IOException { ConfigInternal config = ACConfigManager.getConfigUnsupported(); - String engineContent = Fetch.get(config.rulePack+"/ace.js")+";var ace_checker = new ace.Checker();"; + String engineContent = Fetch.get(config.rulePack+"/ace.js", config.ignoreHTTPSErrors)+";var ace_checker = new ace.Checker();"; // Creates and enters a Context. The Context stores information // about the execution environment of a script. diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java index 6a0cf0f8f..2962ff982 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java @@ -17,11 +17,11 @@ import java.io.IOException; import java.time.Duration; -import java.util.Date; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; +import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriver; import com.google.gson.Gson; @@ -51,7 +51,7 @@ public void loadEngine() throws IOException { engineLoadMode = "INJECT"; } if ("INJECT".equals(engineLoadMode) && engineContent == null) { - engineContent = Fetch.get(config.rulePack+"/ace.js"); + engineContent = Fetch.get(config.rulePack+"/ace.js", config.ignoreHTTPSErrors); } if (config.DEBUG) System.out.println("[INFO] aChecker.loadEngine detected Selenium"); @@ -151,15 +151,21 @@ public ACEReport getCompliance(String label) { cb(e); } """, gson.toJson(config.policies) /* TODO: ${JSON.stringify(ACEngineManager.customRulesets)}; */); - this.driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(60)); - - String jsonReport = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr).toString(); ACEReport report; - if (!jsonReport.startsWith("{\"results\":[")) { - throw new ACError(jsonReport); - } else { - report = gson.fromJson(jsonReport, ACEReport.class); + try { + this.driver.manage().timeouts().scriptTimeout(Duration.ofMinutes(60)); + this.driver.manage().timeouts().setScriptTimeout(Duration.ofMinutes(60)); + String jsonReport = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr).toString(); + if (!jsonReport.startsWith("{\"results\":[")) { + throw new ACError(jsonReport); + } else { + report = gson.fromJson(jsonReport, ACEReport.class); + } + } catch (TimeoutException err) { + System.err.println("TIMEOUT?!"); + throw err; } + // TODO: // String getPolicies = "return new window.ace_ibma.Checker().rulesetIds;"; // if (curPol != null && !checkPolicy) { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java index c827fb3ce..fed0a304a 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java @@ -40,7 +40,7 @@ public class ReporterManager { private static Gson gson = new Gson(); private static ReporterManager singleton = null; public static ReporterManager get() { - if (singleton == null) throw new ACError("RepoterManager not intialized"); + if (singleton == null) throw new ACError("ReporterManager not intialized"); return singleton; } public static ReporterManager initialize(ConfigInternal config, IAbstractAPI absAPI, Guideline[] rulesets) { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java index 74ca68891..45b7ed982 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java @@ -22,12 +22,57 @@ import java.net.URL; import com.google.gson.Gson; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.X509TrustManager; + public class Fetch { private Fetch() {} private static Gson gson = new Gson(); - + public static String get(String urlStr) throws IOException { + return get(urlStr, false); + } + + public static String get(String urlStr, boolean ignoreSSL) throws IOException { + SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory(); + HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier(); + + if (ignoreSSL) { + try { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, new TrustManager[] { new X509TrustManager() { + + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { + } + + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[0]; + } + }}, new java.security.SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + } catch (Error err) { + System.err.println("Ignoring SSL Err! "+err); + } catch (Exception err2) { + System.err.println("Ignoring SSL Err! "+err2); + } + } URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); @@ -37,14 +82,26 @@ public static String get(String urlStr) throws IOException { while ((output = br.readLine()) != null) { sb.append(output); } + if (ignoreSSL) { + HttpsURLConnection.setDefaultSSLSocketFactory(factory); + HttpsURLConnection.setDefaultHostnameVerifier(verifier); + } return sb.toString(); } public static T[] getJSONArr(String urlStr, Class clazz) throws IOException { - return gson.fromJson(Fetch.get(urlStr), clazz); + return getJSONArr(urlStr, clazz, false); + } + + public static T[] getJSONArr(String urlStr, Class clazz, boolean ignoreHTTPSErrors) throws IOException { + return gson.fromJson(Fetch.get(urlStr, ignoreHTTPSErrors), clazz); } public static T getJSONObj(String urlStr, Class clazz) throws IOException { - return gson.fromJson(Fetch.get(urlStr), clazz); + return getJSONObj(urlStr, clazz, false); + } + + public static T getJSONObj(String urlStr, Class clazz, boolean ignoreHTTPSErrors) throws IOException { + return gson.fromJson(Fetch.get(urlStr, ignoreHTTPSErrors), clazz); } } diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index d062fda8c..8a2983f30 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -19,18 +19,52 @@ import static org.junit.Assert.*; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Arrays; +import java.util.Map; +import java.util.List; +import java.util.HashSet; +import java.util.Set; import org.junit.AfterClass; import org.junit.BeforeClass; import org.openqa.selenium.chrome.ChromeDriver; import com.google.common.io.Files; +import com.google.gson.Gson; +import com.ibm.able.config.ACConfigManager; import com.ibm.able.engine.ACReport; +import com.ibm.able.engine.ACReport.Result; import com.ibm.able.report.BaselineManager.eAssertResult; public class AccessibilityCheckerTest { + public static class UnitTestInfoResult { + public String ruleId; + public String reasonId; + public String category; + public String message; + public String[] messageArgs; + public String[] value; + public Map path; + + public boolean matches(Result result) { + return ruleId.equals(result.ruleId) + && reasonId.equals(result.reasonId) + && category.equals(result.category) + && message.equals(result.message) + && value[1].equals(result.value[1]) + && path.get("dom").equals(result.path.get("dom")) + && path.get("aria").equals(result.path.get("aria")); + } + } + public static class UnitTestInfo { + public String[] ruleIds; + public UnitTestInfoResult[] results; + } private static ChromeDriver driver; /** @@ -70,4 +104,111 @@ public class AccessibilityCheckerTest { assertEquals(eAssertResult.PASS, AccessibilityChecker.assertCompliance(report)); Paths.get("baselines", "getComplianceTest3.json").toFile().delete(); } + + // @Test public void getComplianceLong() { + // AccessibilityCheckerTest.driver.get("https://openliberty.io/docs/latest/reference/javadoc/liberty-jakartaee8-javadoc.html?path=liberty-javaee8-javadoc/index-all.html"); + // ACReport report = AccessibilityChecker.getCompliance(driver, "getComplianceLong"); + // assertNotNull(report); + // assertTrue(report.results.length > 0); + // } + + private void listFiles(File f, java.util.List retFiles) { + if (f.isFile() && f.exists() && (f.getName().endsWith("html") || f.getName().endsWith("htm"))) { + retFiles.add(f); + } else if (f.isDirectory()) { + for (File subF: f.listFiles((testFile, name) -> testFile.isDirectory() || name.endsWith(".htm") || name.endsWith(".html"))) { + listFiles(subF, retFiles); + } + } + + } + @Test public void getComplianceTestsuite() throws IOException { + ACConfigManager.resetConfig(); + File configFile = new File("achecker.json"); + try { + configFile.delete(); + FileWriter myWriter = new FileWriter("achecker.json"); + myWriter.write(""" +{ + "customRuleServer": true, + "rulePack": "https://localhost:9445/rules/archives/preview/js", + "ruleArchive": "preview", + "ignoreHTTPSErrors": true, + "policies": [ "IBM_Accessibility", "IBM_Accessibility_next"], + "failLevels": [ "violation", "potentialviolation" ], + "reportLevels": [ + "violation", + "potentialviolation", + "recommendation", + "potentialrecommendation", + "manual", + "pass" + ], + "outputFormat": [ "json" ], + "label": [ + "IBMa-Node-TeSt" + ] +} +"""); + myWriter.close(); + ACConfigManager.getConfig(); + + Gson gson = new Gson(); + File testRootDir = Paths.get(System.getProperty("user.dir"), "..","..","accessibility-checker-engine","test","v2","checker","accessibility","rules").toFile(); + ArrayList testFiles = new ArrayList<>(); + listFiles(testRootDir, testFiles); + + + // Skip test cases that don't work in this environment (e.g., can't disable meta refresh in chrome) + Set skipList = new HashSet<>(Arrays.asList(new File[] { + //not in karma conf file + Paths.get(testRootDir.getAbsolutePath(), "a_text_purpose_ruleunit", "A-hasTextEmbedded.html").toFile(), + // path.join(testRootDir, "a_text_purpose_ruleunit", "A-nonTabable.html"), + + // Meta refresh + Paths.get(testRootDir.getAbsolutePath(), "meta_refresh_delay_ruleunit", "Meta-invalidRefresh.html").toFile(), + Paths.get(testRootDir.getAbsolutePath(), "meta_refresh_delay_ruleunit", "Meta-validRefresh.html").toFile(), + Paths.get(testRootDir.getAbsolutePath(), "meta_redirect_optional_ruleunit", "Meta-RefreshZero.html").toFile(), + + // CSS test issues + Paths.get(testRootDir.getAbsolutePath(), "style_color_misuse_ruleunit","D543.html").toFile(), + Paths.get(testRootDir.getAbsolutePath(), "style_before_after_review_ruleunit","D100.html").toFile(), + + // Misc + // path.join(testRootDir, "aria_banner_label_unique_ruleunit", "validLandMarks-testCaseFromAnn.html"), + })); + + for (File testFile: testFiles) { + if (skipList.contains(testFile)) continue; + AccessibilityCheckerTest.driver.get("file://"+testFile.getAbsolutePath()); + ACReport report = AccessibilityChecker.getCompliance(driver, testFile.getAbsolutePath().substring(testRootDir.getAbsolutePath().length())); + String unitTestInfoStr = AccessibilityCheckerTest.driver.executeScript("return JSON.stringify((typeof (window.UnitTest) !== 'undefined' && window.UnitTest))").toString(); + if (!"false".equals(unitTestInfoStr)) { + System.out.print("."); + UnitTestInfo expectedInfo = gson.fromJson(unitTestInfoStr, UnitTestInfo.class); + List coveredRuleIds = Arrays.asList(expectedInfo.ruleIds); + if (expectedInfo != null && expectedInfo.ruleIds != null && expectedInfo.ruleIds.length > 0) { + List actualIssues = new LinkedList<>(Arrays.stream(report.results).filter(actualIssue -> coveredRuleIds.contains(actualIssue.ruleId)).toList()); + List expectedIssues = new LinkedList<>(Arrays.asList(expectedInfo.results)); + for (int idxActual=0; idxActual Date: Mon, 12 Aug 2024 15:50:58 -0500 Subject: [PATCH 012/161] Add java test to PRs --- .github/workflows/test.yml | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e7af5a6a4..508d822a7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -360,6 +360,45 @@ jobs: - run: npm run wdio working-directory: accessibility-checker/test/webdriverio +############################################################################### +# Java test +#### + java-accessibility-checker-test: + runs-on: ubuntu-22.04 + + strategy: + matrix: + node-version: [18.x] + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v4 + with: + distribution: 'semeru' # See 'Supported distributions' for available options + java-version: '17' + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + - name: Latest Chrome + uses: browser-actions/setup-chrome@v1 + with: + chrome-version: latest + id: setup-chrome + - run: npm install + working-directory: rule-server + - run: npm run build + working-directory: rule-server + - run: node main.js & + working-directory: rule-server/dist + - run: sleep 10 + working-directory: rule-server/dist + + - run: ./gradlew test + working-directory: java-accessibility-checker + ############################################################################### # Karma Tests #### From 105622d5306aeaf0c339dcd47eff867572086405 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 15:51:11 -0500 Subject: [PATCH 013/161] Make headless --- .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index 8a2983f30..c552f1aa6 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -33,6 +33,7 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; import com.google.common.io.Files; import com.google.gson.Gson; @@ -74,7 +75,9 @@ public static class UnitTestInfo { String workingDir = System.getProperty("user.dir"); String chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; System.setProperty("webdriver.chrome.driver", chromeDriverDir); - AccessibilityCheckerTest.driver = new ChromeDriver(); + ChromeOptions options = new ChromeOptions(); + options.addArguments("--headless", "--disable-gpu", "--window-size=1920,1200","--ignore-certificate-errors"); + AccessibilityCheckerTest.driver = new ChromeDriver(options); } /** From f7f0e3ec76ece34a70cc0747f2b984672766b98e Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 16:01:24 -0500 Subject: [PATCH 014/161] Git chromedriver --- .github/workflows/test.yml | 1 + .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 508d822a7..3e7172942 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -386,6 +386,7 @@ jobs: uses: browser-actions/setup-chrome@v1 with: chrome-version: latest + install-chromedriver: true id: setup-chrome - run: npm install working-directory: rule-server diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index c552f1aa6..fdeca62ab 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -73,7 +73,10 @@ public static class UnitTestInfo { */ @BeforeClass public static void setup() { String workingDir = System.getProperty("user.dir"); - String chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; + String chromeDriverDir = System.getenv("chromedriver-path"); + if (chromeDriverDir == null) { + chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; + } System.setProperty("webdriver.chrome.driver", chromeDriverDir); ChromeOptions options = new ChromeOptions(); options.addArguments("--headless", "--disable-gpu", "--window-size=1920,1200","--ignore-certificate-errors"); From 1fc3cd566f9008c512173325a5643fbaebd2d290 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 16:30:12 -0500 Subject: [PATCH 015/161] debug --- .../lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index fdeca62ab..760874a7d 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -77,6 +77,7 @@ public static class UnitTestInfo { if (chromeDriverDir == null) { chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; } + System.out.println("Chrome driver: "+chromeDriverDir); System.setProperty("webdriver.chrome.driver", chromeDriverDir); ChromeOptions options = new ChromeOptions(); options.addArguments("--headless", "--disable-gpu", "--window-size=1920,1200","--ignore-certificate-errors"); From 72538c9d735751a37b4210c9742a3b797f7846f7 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 16:39:56 -0500 Subject: [PATCH 016/161] Add env --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3e7172942..942a428ca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -399,6 +399,8 @@ jobs: - run: ./gradlew test working-directory: java-accessibility-checker + env: + chromedriver-path: ${{ steps.setup-chrome.outputs.chromedriver-path }} ############################################################################### # Karma Tests From b796bc734a707db1fa92c5e42068cabf0cdd2b66 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 17:06:19 -0500 Subject: [PATCH 017/161] Chrome driver dir --- .github/workflows/test.yml | 2 +- .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 942a428ca..eac8f320e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -400,7 +400,7 @@ jobs: - run: ./gradlew test working-directory: java-accessibility-checker env: - chromedriver-path: ${{ steps.setup-chrome.outputs.chromedriver-path }} + chromedriverpath: ${{ steps.setup-chrome.outputs.chromedriver-path }} ############################################################################### # Karma Tests diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index 760874a7d..505641ff4 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -73,7 +73,7 @@ public static class UnitTestInfo { */ @BeforeClass public static void setup() { String workingDir = System.getProperty("user.dir"); - String chromeDriverDir = System.getenv("chromedriver-path"); + String chromeDriverDir = System.getenv("chromedriverpath"); if (chromeDriverDir == null) { chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; } From cf70577f7fe3bcb2ae90df29a1eeb59d3e55767b Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 17:25:48 -0500 Subject: [PATCH 018/161] headless new --- .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index 505641ff4..0b58953e0 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -80,7 +80,9 @@ public static class UnitTestInfo { System.out.println("Chrome driver: "+chromeDriverDir); System.setProperty("webdriver.chrome.driver", chromeDriverDir); ChromeOptions options = new ChromeOptions(); - options.addArguments("--headless", "--disable-gpu", "--window-size=1920,1200","--ignore-certificate-errors"); + options.addArguments("--headless=new"); + // options.setImplicitWaitTimeout + // options.addArguments("--headless", "--disable-gpu", "--window-size=1920,1200","--ignore-certificate-errors"); AccessibilityCheckerTest.driver = new ChromeDriver(options); } From c744a8fe2c8ea142e39da288fbe7a6ca2619cadd Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 17:39:39 -0500 Subject: [PATCH 019/161] debug --- .github/workflows/test.yml | 4 ++++ .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index eac8f320e..097de5692 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -397,6 +397,10 @@ jobs: - run: sleep 10 working-directory: rule-server/dist + - run: | + echo "${{ steps.setup-chrome.outputs.chrome-version }}" + - run: | + echo "${{ steps.setup-chrome.outputs.chromedriver-version }}" - run: ./gradlew test working-directory: java-accessibility-checker env: diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index 0b58953e0..16fa57f18 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -77,7 +77,6 @@ public static class UnitTestInfo { if (chromeDriverDir == null) { chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; } - System.out.println("Chrome driver: "+chromeDriverDir); System.setProperty("webdriver.chrome.driver", chromeDriverDir); ChromeOptions options = new ChromeOptions(); options.addArguments("--headless=new"); From 71c19bf153bdd53ecd3460a502882749fc7e55fe Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 17:43:48 -0500 Subject: [PATCH 020/161] debug --- .github/workflows/test.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 097de5692..00c49f1cd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -397,10 +397,8 @@ jobs: - run: sleep 10 working-directory: rule-server/dist - - run: | - echo "${{ steps.setup-chrome.outputs.chrome-version }}" - - run: | - echo "${{ steps.setup-chrome.outputs.chromedriver-version }}" + - run: echo "${{ steps.setup-chrome.outputs.chrome-version }}" + - run: echo "${{ steps.setup-chrome.outputs.chromedriver-version }}" - run: ./gradlew test working-directory: java-accessibility-checker env: From 3dd70777cad49b33902a458439690aad24ea43c8 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 19:44:24 -0500 Subject: [PATCH 021/161] Debug --- .../test/java/com/ibm/able/AccessibilityCheckerTest.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index 16fa57f18..ecf176d05 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -32,6 +32,7 @@ import org.junit.AfterClass; import org.junit.BeforeClass; +import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; @@ -82,7 +83,13 @@ public static class UnitTestInfo { options.addArguments("--headless=new"); // options.setImplicitWaitTimeout // options.addArguments("--headless", "--disable-gpu", "--window-size=1920,1200","--ignore-certificate-errors"); - AccessibilityCheckerTest.driver = new ChromeDriver(options); + try { + AccessibilityCheckerTest.driver = new ChromeDriver(options); + } catch (SessionNotCreatedException e) { + System.out.println(e.getMessage()); + System.out.println(e.getAdditionalInformation()); + throw e; + } } /** From a18ad318d8670301193c477f9e4b5f350243b864 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 20:03:30 -0500 Subject: [PATCH 022/161] Set bin path --- .github/workflows/test.yml | 2 +- .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 00c49f1cd..ed4659b0f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -403,7 +403,7 @@ jobs: working-directory: java-accessibility-checker env: chromedriverpath: ${{ steps.setup-chrome.outputs.chromedriver-path }} - + chromebinpath: ${{ steps.setup-chrome.outputs.chrome-path }} ############################################################################### # Karma Tests #### diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index ecf176d05..7db801037 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -75,11 +75,13 @@ public static class UnitTestInfo { @BeforeClass public static void setup() { String workingDir = System.getProperty("user.dir"); String chromeDriverDir = System.getenv("chromedriverpath"); + ChromeOptions options = new ChromeOptions(); if (chromeDriverDir == null) { chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; + } else { + options.setBinary(System.getenv("chromebinpath")); } System.setProperty("webdriver.chrome.driver", chromeDriverDir); - ChromeOptions options = new ChromeOptions(); options.addArguments("--headless=new"); // options.setImplicitWaitTimeout // options.addArguments("--headless", "--disable-gpu", "--window-size=1920,1200","--ignore-certificate-errors"); From ab3921541579aaefd0a3517f3b2ff67347cd7fb1 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 20:29:39 -0500 Subject: [PATCH 023/161] Fix test --- .github/workflows/test.yml | 3 --- .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ed4659b0f..60e945a14 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -396,9 +396,6 @@ jobs: working-directory: rule-server/dist - run: sleep 10 working-directory: rule-server/dist - - - run: echo "${{ steps.setup-chrome.outputs.chrome-version }}" - - run: echo "${{ steps.setup-chrome.outputs.chromedriver-version }}" - run: ./gradlew test working-directory: java-accessibility-checker env: diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index 7db801037..e30e18718 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -225,6 +225,7 @@ private void listFiles(File f, java.util.List retFiles) { System.out.println(); } finally { configFile.delete(); + ACConfigManager.resetConfig(); } } From e70ef31702e1165465ab7f1528d4fa7dde61be04 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 12 Aug 2024 20:45:05 -0500 Subject: [PATCH 024/161] Output progress --- .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index e30e18718..e5f6294a2 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -201,10 +201,11 @@ private void listFiles(File f, java.util.List retFiles) { ACReport report = AccessibilityChecker.getCompliance(driver, testFile.getAbsolutePath().substring(testRootDir.getAbsolutePath().length())); String unitTestInfoStr = AccessibilityCheckerTest.driver.executeScript("return JSON.stringify((typeof (window.UnitTest) !== 'undefined' && window.UnitTest))").toString(); if (!"false".equals(unitTestInfoStr)) { - System.out.print("."); UnitTestInfo expectedInfo = gson.fromJson(unitTestInfoStr, UnitTestInfo.class); List coveredRuleIds = Arrays.asList(expectedInfo.ruleIds); if (expectedInfo != null && expectedInfo.ruleIds != null && expectedInfo.ruleIds.length > 0) { + System.out.println(testFile.getAbsolutePath()); + System.out.flush(); List actualIssues = new LinkedList<>(Arrays.stream(report.results).filter(actualIssue -> coveredRuleIds.contains(actualIssue.ruleId)).toList()); List expectedIssues = new LinkedList<>(Arrays.asList(expectedInfo.results)); for (int idxActual=0; idxActual Date: Mon, 12 Aug 2024 20:54:15 -0500 Subject: [PATCH 025/161] change path --- .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index e5f6294a2..18fbf8196 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -204,7 +204,7 @@ private void listFiles(File f, java.util.List retFiles) { UnitTestInfo expectedInfo = gson.fromJson(unitTestInfoStr, UnitTestInfo.class); List coveredRuleIds = Arrays.asList(expectedInfo.ruleIds); if (expectedInfo != null && expectedInfo.ruleIds != null && expectedInfo.ruleIds.length > 0) { - System.out.println(testFile.getAbsolutePath()); + System.out.println(testFile.getCanonicalPath()); System.out.flush(); List actualIssues = new LinkedList<>(Arrays.stream(report.results).filter(actualIssue -> coveredRuleIds.contains(actualIssue.ruleId)).toList()); List expectedIssues = new LinkedList<>(Arrays.asList(expectedInfo.results)); From b03f45f8fc1ce66a43bc2f0ef8365d574e13706b Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 10:12:11 -0500 Subject: [PATCH 026/161] Metrics and copyright --- .../src/main/java/com/ibm/able/Library.java | 10 -- .../src/main/java/com/ibm/able/abs/MyFS.java | 15 ++ .../enginecontext/EngineContextLocal.java | 15 ++ .../enginecontext/EngineContextManager.java | 4 + .../com/ibm/able/report/ACReporterJSON.java | 15 ++ .../ibm/able/report/ACReporterMetrics.java | 144 ++++++++++++++++++ .../java/com/ibm/able/report/IReporter.java | 15 ++ .../com/ibm/able/report/ReporterFile.java | 15 ++ .../com/ibm/able/report/ReporterManager.java | 3 +- .../com/ibm/able/report/ReporterStored.java | 15 ++ .../ibm/able/AccessibilityCheckerTest.java | 2 +- 11 files changed, 240 insertions(+), 13 deletions(-) delete mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/Library.java create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/Library.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/Library.java deleted file mode 100644 index e1d609b90..000000000 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/Library.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * This source file was generated by the Gradle 'init' task - */ -package com.ibm.able; - -public class Library { - public boolean someLibraryMethod() { - return true; - } -} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java index c0cc2c0cb..0bea28638 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java @@ -1,3 +1,18 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ package com.ibm.able.abs; import com.ibm.able.engine.ACReport; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java index bb07b434c..443c06d24 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java @@ -81,4 +81,19 @@ public Rule[] getRules() { return gson.fromJson(jsonGuidelines, Rule[].class); } + public String encodeURIComponent(String s) { + if (engine == null) { + // Creates and enters a Context. The Context stores information + // about the execution environment of a script. + engine = Context.enter(); + + // Initialize the standard objects (Object, Function, etc.) + // This must be done before scripts can be executed. Returns + // a scope object that we use in later calls. + engineScope = engine.initStandardObjects(); + } + String scriptStr = String.format("encodeURIComponent(`%s`)", s); + String result = engine.evaluateString(engineScope, scriptStr, "", 1, null).toString(); + return result; + } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java index 3a2188a1a..e824eaedd 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java @@ -23,6 +23,10 @@ public class EngineContextManager { private EngineContextManager() {} + + public static String encodeURIComponent(String s) { + return new EngineContextLocal().encodeURIComponent(s); + } public static IEngineContext getEngineContext(Object contentContext) { IEngineContext engineContext = null; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java index 484705f63..9da2aa017 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java @@ -1,3 +1,18 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ package com.ibm.able.report; import java.util.Date; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java new file mode 100644 index 000000000..a930cc539 --- /dev/null +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java @@ -0,0 +1,144 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able.report; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.ibm.able.config.ConfigInternal; +import com.ibm.able.engine.Guideline; +import com.ibm.able.enginecontext.EngineContextManager; +import com.ibm.able.util.Fetch; + +/******************************************************************************* + * NAME: ACMetricsLogger.js + * DESCRIPTION: Common Metrics logger object which can be shared between tools + * to upload metrics of the tool to the metrics server. + *******************************************************************************/ + +public class ACReporterMetrics implements IReporter { + private String policies; + private String metricsURLV2 = "https://able.ibm.com/tools"; + private String toolName; + private Map> scanTimesV2 = new HashMap<>(); + + public ACReporterMetrics(String toolName, String[] policies) { + this.policies = String.join(",", policies); + // Init all the local object variables + this.toolName = toolName; + } + + @Override + public String name() { + return "metrics"; + } + + /** + * This function is responsible for profiling the testcases and adding the scan time to the global + * array which will be sent to the metrics server to log the number of scans that were performed. + * This function profiles scanTimes for the V2 metric server: + * https://aat.w3ibm.mybluemix.net + * + * In the case that user provides any url that is https://aat* it will upload based on accountId + * + * @param {String} scanTime - Provide the time it took for the testcase to run + * @param {String} profile - The type of profile the scan time is for: + * i.e. browser information, features, etc... + * + * @return N/A - Global scanTimesV2 object is updated with the time + * + * @memberOf this + */ + @Override + public ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, ReporterStored storedReport) { + if (config.label == null || Arrays.asList(config.label).contains("IBMa-Java-TeSt")) { + // URI encode the profile text provided + String profile = EngineContextManager.encodeURIComponent(storedReport.scanProfile); + if (!scanTimesV2.containsKey(profile)) { + scanTimesV2.put(profile, new ArrayList()); + } + // Add the time it took for the testcase to run to the global array, indexed by the profile + scanTimesV2.get(profile).add(""+storedReport.engineReport.summary.scanTime); + } + return null; + }; + + /** + * This function is responsible for uploading scan results to the metrics server: + * https://aat.w3ibm.mybluemix.net + * + * @param {Function} done - The browser on which the testcases were run on + * + * @return N/A - performs the upload of the metrics to the server + * + * @memberOf this + */ + @Override + public ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, long endReport, + CompressedReport[] compressedReports) + { + try { + // Variable Declaration + String accountId = ""; + + // Loop over all the profiles with in the scanTime Object + for (Entry> entry: scanTimesV2.entrySet()) { + // Loop over all the V2 Scan Times until it reaches 0 + if (!entry.getValue().isEmpty()) { + String preQS = "?t=" + this.toolName + "&tag=" + entry.getKey() + "&a=" + accountId + "&pol=" + this.policies + "&st="; + StringBuilder qsBuilder = new StringBuilder(); + ArrayList times = entry.getValue(); + for (int idx=0; idx < times.size(); ++idx) { + qsBuilder.append(times.get(idx)); + qsBuilder.append(","); + + if ((idx % 150) == 0) { + String qs = preQS + qsBuilder.substring(0, qsBuilder.length()-1); + + // Dispatch the call to the metrics server + try { + System.out.println(this.metricsURLV2 + "/api/pub/meter/v2" + qs.toString()); + Fetch.get(this.metricsURLV2 + "/api/pub/meter/v2" + qs.toString()); + } catch (Throwable t) { + System.err.println(t); + } + } + qsBuilder = new StringBuilder(); + } + if (qsBuilder.length() > 0) { + String qs = preQS + qsBuilder.substring(0, qsBuilder.length()-1); + + // Dispatch the call to the metrics server + try { + System.out.println(this.metricsURLV2 + "/api/pub/meter/v2" + qs.toString()); + Fetch.get(this.metricsURLV2 + "/api/pub/meter/v2" + qs.toString()); + } catch (Throwable t) { + System.err.println(t); + } + } + } + } + } catch (Throwable t) { + System.err.println(t); + t.printStackTrace(); + } + return null; + }; +}; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java index 24f28f17d..cda60734c 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java @@ -1,3 +1,18 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ package com.ibm.able.report; import com.ibm.able.config.ConfigInternal; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java index aeeec3c03..bc5895324 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java @@ -1,3 +1,18 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ package com.ibm.able.report; public class ReporterFile { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java index fed0a304a..e53c08f1b 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java @@ -59,8 +59,7 @@ private ReporterManager(ConfigInternal config, IAbstractAPI absAPI, Guideline[] this.absAPI = absAPI; this.rulesets = rulesets; if (config.perfMetrics) { - // TODO: - // reporters.add(new ACReporterMetrics(config.toolName, config.policies)); + reporters.add(new ACReporterMetrics(config.toolName, config.policies)); } if (!Arrays.asList(config.outputFormat).contains("disable")) { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java index cf41153a8..c093c05df 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java @@ -1,3 +1,18 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ package com.ibm.able.report; import com.ibm.able.engine.ACReport; diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index 18fbf8196..24941604e 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -163,7 +163,7 @@ private void listFiles(File f, java.util.List retFiles) { ], "outputFormat": [ "json" ], "label": [ - "IBMa-Node-TeSt" + "IBMa-Java-TeSt2" ] } """); From f332d653004f1557925c0216ff7d6fcea2699dfd Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 11:22:41 -0500 Subject: [PATCH 027/161] Don't record our own tests --- .../src/main/java/com/ibm/able/report/ACReporterMetrics.java | 2 +- .../src/test/java/com/ibm/able/AccessibilityCheckerTest.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java index a930cc539..b7aba6acf 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java @@ -68,7 +68,7 @@ public String name() { */ @Override public ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, ReporterStored storedReport) { - if (config.label == null || Arrays.asList(config.label).contains("IBMa-Java-TeSt")) { + if (config.label == null || !Arrays.asList(config.label).contains("IBMa-Java-TeSt")) { // URI encode the profile text provided String profile = EngineContextManager.encodeURIComponent(storedReport.scanProfile); if (!scanTimesV2.containsKey(profile)) { diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java index 24941604e..5a730da9e 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java @@ -103,6 +103,7 @@ public static class UnitTestInfo { } @Test public void getCompliance() { + ACConfigManager.getConfig().label = new String[] { "IBMa-Java-TeSt" }; AccessibilityCheckerTest.driver.get("https://altoromutual.12mc9fdq8fib.us-south.codeengine.appdomain.cloud/"); ACReport report = AccessibilityChecker.getCompliance(driver, "getComplianceTest"); assertNotNull(report); @@ -163,7 +164,7 @@ private void listFiles(File f, java.util.List retFiles) { ], "outputFormat": [ "json" ], "label": [ - "IBMa-Java-TeSt2" + "IBMa-Java-TeSt" ] } """); From 7d14a3ae66e6210563d5de850981f25a81919f8b Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 12:08:14 -0500 Subject: [PATCH 028/161] Javadoc updates --- .../com/ibm/able/AccessibilityChecker.java | 62 +++++++++---------- .../com/ibm/able/config/ACConfigManager.java | 23 ++----- .../ibm/able/report/ACReporterMetrics.java | 26 -------- .../com/ibm/able/report/BaselineManager.java | 37 +++-------- 4 files changed, 44 insertions(+), 104 deletions(-) diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java index 6343f976b..b26d990b1 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java @@ -40,23 +40,13 @@ public class AccessibilityChecker { private static IAbstractAPI myFS = new MyFS(); private static IEngineContext localEngine; - /** - * This function is responsible performing a scan based on the context that is provided, following are - * the supported context type: - * Single node (HTMLElement) - * Local file path (String) - * URL (String) - * document node - * data stream for html content (String) - * - * Future Items - * Multiple node (Array of HTMLElements) ---> FUTURE - * - * @param {(Webdriver|Puppeteer Page |)} content - Provide the context to scan, which includes the items from above. - * @param {String} label - Provide a label for the scan that is being performed - * @param {Function} callback - (optional) Provide callback function which will be executed once the results are extracted. - * @return Promise with the ICheckerResult - */ + /** + * This function is responsible performing a scan based on the context that is provided, following are + * the supported context type: WebDriver + * @param content The WebDriver with the content to scan + * @param label Provide a label for the scan that is being performed + * @return Resulting report + */ public static ACReport getCompliance(Object content, String label) { if (content == null) { System.err.println("aChecker: Unable to get compliance of null or undefined object"); @@ -111,14 +101,27 @@ private static void initialize() { * be used to perform the check, in the case no baseline is provided then we comply with only failing if * there is a sinble violation which falls into failLevels. * - * @param {ReportResult} actual - the actual results object provided by the user, this object should follow the + * @param actual the actual results object provided by the user, this object should follow the * same format as outlined in the return of aChecker.buildReport function. * - * @return {int} - return 0 in the case actual matches baseline or no violations fall into failsLevels, + * @return return 0 in the case actual matches baseline or no violations fall into failsLevels, * return 1 in the case actual results does not match baseline results, * return 2 in the case that there is a failure based on failLevels (this means no baseline found). * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. */ + + /** + * This function is responsible for comparing the scan results with baseline or checking that there are + * no violations which fall into the failsLevels levels. In the case a baseline is found then baseline will + * be used to perform the check, in the case no baseline is provided then we comply with only failing if + * there is a sinble violation which falls into failLevels. + * @param report the actual results object provided by the user, this object should follow the + * same format as outlined in the return of aChecker.buildReport function. + * @return return 0 in the case actual matches baseline or no violations fall into failsLevels, + * return 1 in the case actual results does not match baseline results, + * return 2 in the case that there is a failure based on failLevels (this means no baseline found). + * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. + */ public static eAssertResult assertCompliance(ACReport report) { return BaselineManager.assertCompliance(report); } @@ -129,10 +132,6 @@ public static eAssertResult assertCompliance(ACReport report) { // * @param {Object} results - Provide the results from the scan. // * // * @return {String} resultsString - String representation of the results/violations. -// * -// * PUBLIC API -// * -// * @memberOf this // */ // export function stringifyResults(report: ICheckerReport) : string { // return ReporterManager.stringifyResults(report) @@ -145,9 +144,9 @@ public static void close() { /** * This function is responsible for getting the diff results based on label for a scan that was already performed. * - * @param {String} label - Provide a lable for which to get the diff results for. + * @param label Provide a label for which to get the diff results for. * - * @return {Object} - return the diff results object from global space based on label provided, the object will be + * @return return the diff results object from global space based on label provided, the object will be * in the same format as outlined in the return of aChecker.diffResultsWithExpected function. */ public static DiffResult[] getDiffResults(String label) { @@ -157,9 +156,9 @@ public static DiffResult[] getDiffResults(String label) { /** * This function is responsible for getting the baseline object for a label that was provided. * - * @param {String} label - Provide a lable for which to get the baseline for. + * @param label Provide a label for which to get the baseline for. * - * @return {Object} - return the baseline object from global space based on label provided, the object will be + * @return return the baseline object from global space based on label provided, the object will be * in the same format as outlined in the return of aChecker.buildReport function. */ public static ACReport getBaseline(String label) { @@ -169,13 +168,10 @@ public static ACReport getBaseline(String label) { /** * This function is responsible for comparing actual with expected and returning all the differences as an array. * - * @param {Object} actual - Provide the actual object to be used for compare - * @param {Object} expected - Provide the expected object to be used for compare - * @param {boolean} clean - Provide a boolean if both the actual and expected objects need to be cleaned - * cleaning refers to converting the objects to match with a basic compliance - * compare of xpath and ruleId. + * @param actual Provide the actual object to be used for compare + * @param expected Provide the expected object to be used for compare * - * @return {Object} differences - return an array of diff objects that were found, following is the format of the object: + * @return differences - return an array of diff objects that were found, following is the format of the object: * [ * { * "kind": "E", diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java index 713870b1d..7d116ad00 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java @@ -111,11 +111,9 @@ private static String findLatestArchiveId(Archive[] archives, String toolVersion * Need to change array of policies into a string * ["CI162_5_2_DCP070116","CI162_5_2_DCP070116"] to "CI162_5_2_DCP070116,CI162_5_2_DCP070116" * - * @param {Object} ACConfig - Provide the config object in which needs to be processed. + * @param ACConfig Provide the config object in which needs to be processed. * - * @return {Object} ACConfig - return the config object which has been made engine readable - * - * @memberOf this + * @return ConfigInternal - return the config object which has been made engine readable */ private static ConfigInternal processACConfig(ConfigInternal ACConfig) throws IOException { String[] validArchiveKeywords = { "latest", "preview", "versioned" }; @@ -197,12 +195,7 @@ private static ConfigInternal processACConfig(ConfigInternal ACConfig) throws IO * This function is responsible initializing all the default values for the configurations, in the case any * of the config options are missing. * - * @param {Object} config - Provide the config object in which we need to initialize the default values. - * - * @return {Object} config - return the config object which has all the default values, in the case - * some of the options are null or undefined. - * - * @memberOf this + * @param config Provide the config object in which we need to initialize the default values. */ private static void initializeDefaults(ConfigInternal config) { // Use an unpopulated config as the default values @@ -247,8 +240,6 @@ private static void initializeDefaults(ConfigInternal config) { * * @return {Object} config - return the config object that was read in, refer to function initializeDefaults * to view how the object is to be constructed. - * - * @memberOf this */ private static ConfigInternal loadConfigFromJSONFile() { // Use an unpopulated config as the default values @@ -300,15 +291,13 @@ private static ConfigInternal loadConfigFromJSONFile() { * function and then the config variables will be assoiciated to the global space so that * they can be accessed from window.__karma__.config * - * @param {Object} config - All the Karma configuration, we will extract what we need from this over + * @param config All the Karma configuration, we will extract what we need from this over * all object, we need the entire object so that we can reasign some config * variables to global scope so that all karma testscases/scripts can access * them. * - * @return - N/A - Object will be processed and all the params that are needed for this module will - * be extracted and then the entire object will be added to global space. - * - * @memberOf this + * @return Object will be processed and all the params that are needed for this module will + * be extracted */ private static ConfigInternal processConfiguration(Config config) { // Use an unpopulated config as the default values diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java index b7aba6acf..00f2a32f1 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java @@ -50,22 +50,6 @@ public String name() { return "metrics"; } - /** - * This function is responsible for profiling the testcases and adding the scan time to the global - * array which will be sent to the metrics server to log the number of scans that were performed. - * This function profiles scanTimes for the V2 metric server: - * https://aat.w3ibm.mybluemix.net - * - * In the case that user provides any url that is https://aat* it will upload based on accountId - * - * @param {String} scanTime - Provide the time it took for the testcase to run - * @param {String} profile - The type of profile the scan time is for: - * i.e. browser information, features, etc... - * - * @return N/A - Global scanTimesV2 object is updated with the time - * - * @memberOf this - */ @Override public ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, ReporterStored storedReport) { if (config.label == null || !Arrays.asList(config.label).contains("IBMa-Java-TeSt")) { @@ -80,16 +64,6 @@ public ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, return null; }; - /** - * This function is responsible for uploading scan results to the metrics server: - * https://aat.w3ibm.mybluemix.net - * - * @param {Function} done - The browser on which the testcases were run on - * - * @return N/A - performs the upload of the metrics to the server - * - * @memberOf this - */ @Override public ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, long endReport, CompressedReport[] compressedReports) diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java index 1415b92d0..179547ee8 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java @@ -112,17 +112,13 @@ public static ACReport getBaseline(String label) { * be used to perform the check, in the case no baseline is provided then we comply with only failing if * there is a sinble violation which falls into failLevels. * - * @param {Object} actual - the actual results object provided by the user, this object should follow the + * @param actualResults the actual results object provided by the user, this object should follow the * same format as outlined in the return of aChecker.buildReport function. * - * @return {int} - return 0 in the case actual matches baseline or no violations fall into failsLevels, + * @return return 0 in the case actual matches baseline or no violations fall into failsLevels, * return 1 in the case actual results does not match baseline results, * return 2 in the case that there is a failure based on failLevels (this means no baseline found). * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. - * - * PUBLIC API - * - * @memberOf this */ public static eAssertResult assertCompliance(ACReport actualResults) { // Get the label directly from the results object, the same label has to match @@ -181,13 +177,10 @@ public static eAssertResult assertCompliance(ACReport actualResults) { /** * This function is responsible for comparing actual with expected and returning all the differences as an array. * - * @param {Object} actual - Provide the actual object to be used for compare - * @param {Object} expected - Provide the expected object to be used for compare - * @param {boolean} clean - Provide a boolean if both the actual and expected objects need to be cleaned - * cleaning refers to converting the objects to match with a basic compliance - * compare of xpath and ruleId. + * @param actual Provide the actual object to be used for compare + * @param expected Provide the expected object to be used for compare * - * @return {Object} differences - return an array of diff objects that were found, following is the format of the object: + * @return differences - return an array of diff objects that were found, following is the format of the object: * [ * { * "kind": "E", @@ -210,10 +203,6 @@ public static eAssertResult assertCompliance(ACReport actualResults) { * "rhs": "dependencies/tools-rules-html/v2/a11y/test/g471/Table-layoutMultiple.html", * } * ] - * - * PUBLIC API - * - * @memberOf this */ public static DiffResult[] diffResultsWithExpected(ACReport actual, ACReport expected) { // Run Deep diff function to compare the actual and expected values. @@ -236,15 +225,11 @@ public static DiffResult[] diffResultsWithExpected(ACReport actual, ACReport exp * This function is responsible for checking if any of the issues reported have any level that falls * into the failsLevel array. * - * @param {Object} results - Provide the scan results, object which would be in the + * @param report Provide the scan results, object which would be in the * the same format as outlined in the return of aChecker.buildReport function. * - * @return {int} - return 1 in the case a single issue was found which is in the failsLevel array. + * @return return 1 in the case a single issue was found which is in the failsLevel array. * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. - * - * PRIVATE METHOD - * - * @memberOf this */ public static int compareBasedOnFailLevels(ACReport report) { // Variable Declaration @@ -269,14 +254,10 @@ public static int compareBasedOnFailLevels(ACReport report) { /** * This function is responsible for getting the diff results based on label for a scan that was already performed. * - * @param {String} label - Provide a lable for which to get the diff results for. + * @param label Provide a label for which to get the diff results for. * - * @return {Object} - return the diff results object from global space based on label provided, the object will be + * @return return the diff results object from global space based on label provided, the object will be * in the same format as outlined in the return of aChecker.diffResultsWithExpected function. - * - * PUBLIC API - * - * @memberOf this */ public static DiffResult[] getDiffResults(String label) { return diffResults.get(label); From 0af9784c8e8c4969460caba099678a417a9f696a Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 12:42:11 -0500 Subject: [PATCH 029/161] Basic javadoc cleanup --- .../com/ibm/able/AccessibilityChecker.java | 106 ++++++++---------- .../java/com/ibm/able/engine/ACEReport.java | 12 +- .../java/com/ibm/able/engine/ACReport.java | 15 +++ 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java index b26d990b1..5a3bdae7b 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java @@ -36,14 +36,27 @@ import com.ibm.able.abs.MyFS; public class AccessibilityChecker { + private AccessibilityChecker() {} + private static boolean initialized = false; private static IAbstractAPI myFS = new MyFS(); private static IEngineContext localEngine; + /** + * Get the processed configuration object + * @return + */ + public static Config getConfig() { + return ACConfigManager.getConfig(); + } + + public static ConfigInternal getConfigUnsupported() { + return ACConfigManager.getConfigUnsupported(); + } + /** - * This function is responsible performing a scan based on the context that is provided, following are - * the supported context type: WebDriver - * @param content The WebDriver with the content to scan + * Perform a scan of the provided context. Currently supported contexts: WebDriver. + * @param content The content to scan. * @param label Provide a label for the scan that is being performed * @return Resulting report */ @@ -67,65 +80,24 @@ public static ACReport getCompliance(Object content, String label) { return finalReport; } - public static Config getConfig() { - return ACConfigManager.getConfig(); - } - - public static ConfigInternal getConfigUnsupported() { - return ACConfigManager.getConfigUnsupported(); - } - - private static void initialize() { - if (initialized) return; - initialized = true; - localEngine = EngineContextManager.getEngineContext(null); - Map refactorMap = new HashMap<>(); - Rule[] rules = localEngine.getRules(); - for (Rule rule: rules) { - if (rule.refactor != null) { - for (String key: rule.refactor.keySet()) { - refactorMap.put(key, rule); - } - } - } - ConfigInternal config = getConfigUnsupported(); - ReporterManager.initialize(config, myFS, localEngine.getGuidelines()); - BaselineManager.initialize(config, myFS, refactorMap); - - Runtime.getRuntime().addShutdownHook(new Thread(() -> AccessibilityChecker.close() )); - } - /** - * This function is responsible for comparing the scan results with baseline or checking that there are - * no violations which fall into the failsLevels levels. In the case a baseline is found then baseline will - * be used to perform the check, in the case no baseline is provided then we comply with only failing if - * there is a sinble violation which falls into failLevels. - * - * @param actual the actual results object provided by the user, this object should follow the - * same format as outlined in the return of aChecker.buildReport function. - * - * @return return 0 in the case actual matches baseline or no violations fall into failsLevels, - * return 1 in the case actual results does not match baseline results, - * return 2 in the case that there is a failure based on failLevels (this means no baseline found). - * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. + * Check the scan results against configured failLevels or against a previously set baseline. + * @param report Report generated by getCompliance + * @return - 0 if report matches baseline, or no issues match failLevels + * - 1 results do not match baseline results + * - 2 failure based on failLevels (this means no baseline found) */ - - /** - * This function is responsible for comparing the scan results with baseline or checking that there are - * no violations which fall into the failsLevels levels. In the case a baseline is found then baseline will - * be used to perform the check, in the case no baseline is provided then we comply with only failing if - * there is a sinble violation which falls into failLevels. - * @param report the actual results object provided by the user, this object should follow the - * same format as outlined in the return of aChecker.buildReport function. - * @return return 0 in the case actual matches baseline or no violations fall into failsLevels, - * return 1 in the case actual results does not match baseline results, - * return 2 in the case that there is a failure based on failLevels (this means no baseline found). - * return -1 in the case that there is an exception that occured in the results object which came from the scan engine. - */ public static eAssertResult assertCompliance(ACReport report) { return BaselineManager.assertCompliance(report); } + /** + * Close the checker and ensure all summary reports are generated + */ + public static void close() { + ReporterManager.get().generateSummaries(); + } + // /** // * This function is responsible for printing the scan results to console. // * @@ -137,9 +109,6 @@ public static eAssertResult assertCompliance(ACReport report) { // return ReporterManager.stringifyResults(report) // } - public static void close() { - ReporterManager.get().generateSummaries(); - } /** * This function is responsible for getting the diff results based on label for a scan that was already performed. @@ -221,4 +190,23 @@ public static Rule[] getRules() { return localEngine.getRules(); } + private static void initialize() { + if (initialized) return; + initialized = true; + localEngine = EngineContextManager.getEngineContext(null); + Map refactorMap = new HashMap<>(); + Rule[] rules = localEngine.getRules(); + for (Rule rule: rules) { + if (rule.refactor != null) { + for (String key: rule.refactor.keySet()) { + refactorMap.put(key, rule); + } + } + } + ConfigInternal config = getConfigUnsupported(); + ReporterManager.initialize(config, myFS, localEngine.getGuidelines()); + BaselineManager.initialize(config, myFS, refactorMap); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> AccessibilityChecker.close() )); + } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java index f153558ef..8c071bd2c 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java @@ -35,15 +35,25 @@ public Result(Result o) { value = o.value.clone(); } public Object[] apiArgs = new Object[]{}; + /** Bounds of the result as would be found in the viewport */ public Bounds bounds = new Bounds(); + /** Category of the result (e.g., accessibility) */ public String category; + /** Result message describing what was found */ public String message; + /** Parameter parts used to construct the message */ public String[] messageArgs; + /** Mapping of "dom", "aria", etc to identify the location of the result */ public Map path; - public String reasonId; + /** Identifier of the rule that triggered the result */ public String ruleId; + /** Identifier indicating the specific reason this issue triggered within the rule */ + public String reasonId; + /** How long this rule took to run */ public int ruleTime; + /** HTML snippet that this result triggered on */ public String snippet; + /** Combination of the level of the result (e.g., ["VIOLATION", "FAIL"]) */ public String[] value; @Override diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java index 33e737bc6..c9258e5ab 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java @@ -69,8 +69,11 @@ public Object clone() { } } public static class Result extends ACEReport.Result implements Cloneable { + /** Did this issue match a baseline */ public boolean ignored = false; + /** Help url for this item */ public String help = ""; + /** Level of the issue (violation, potentialviolation, etc) */ public eRuleLevel level; public Result() {} @@ -82,14 +85,23 @@ public Object clone() { return super.clone(); } } + /** List of items detected by the getCompliance scan */ public Result[] results = new Result[0]; + /** Number of rules executed */ public int numExecuted = 0; + /** Mapping of ruleId to reasonId to a parameterized message */ public Map> nls = new HashMap<>(); + /** Summary of the scan */ public Summary summary = new Summary(); + /** Identifier of the scan (same id used for each scan of the session) */ public String scanID = ""; + /** Identifier for the accessibility-checker tool used to perform the scan */ public String toolID = ""; + /** Label as specified in the getCompliance call that generated the report */ public String label = ""; + /** base64 screenshot, if one was taken */ public String screenshot=null; + /** Amount of time in ms that rules were running */ public int ruleTime = 0; public ACReport() {} @@ -107,6 +119,9 @@ public ACReport(ConfigInternal config, ACEReport engineReport, String label) { this.label = label; } + /** + * Update the summary counts to match the included results + */ public void updateSummaryCounts() { SummaryCounts counts = summary.counts; counts.violation = 0; From 9464e4ca7964c99240afa1fcfd6e3c6182c1a746 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 13:30:14 -0500 Subject: [PATCH 030/161] Test build --- .github/workflows/test.yml | 34 ++++++++++++--- java-accessibility-checker/README-DEV.md | 5 +++ java-accessibility-checker/lib/build.gradle | 46 ++++++++++++++++++++- 3 files changed, 77 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 60e945a14..b8744d426 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -376,12 +376,6 @@ jobs: with: distribution: 'semeru' # See 'Supported distributions' for available options java-version: '17' - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - cache-dependency-path: '**/package-lock.json' - name: Latest Chrome uses: browser-actions/setup-chrome@v1 with: @@ -401,6 +395,34 @@ jobs: env: chromedriverpath: ${{ steps.setup-chrome.outputs.chromedriver-path }} chromebinpath: ${{ steps.setup-chrome.outputs.chrome-path }} + +############################################################################### +# Java test +#### + java-accessibility-checker-buildtest: + runs-on: ubuntu-22.04 + + strategy: + matrix: + node-version: [18.x] + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v4 + with: + distribution: 'semeru' # See 'Supported distributions' for available options + java-version: '17' + - run: ./gradlew jar + working-directory: java-accessibility-checker + env: + chromedriverpath: ${{ steps.setup-chrome.outputs.chromedriver-path }} + chromebinpath: ${{ steps.setup-chrome.outputs.chrome-path }} + - name: Publish to GitHub Packages + run: gradle publish + env: + USERNAME: ${{ github.actor }} + PASSWORD: ${{ secrets.GITHUB_TOKEN }} + ############################################################################### # Karma Tests #### diff --git a/java-accessibility-checker/README-DEV.md b/java-accessibility-checker/README-DEV.md index 0432971e3..2c235c24c 100644 --- a/java-accessibility-checker/README-DEV.md +++ b/java-accessibility-checker/README-DEV.md @@ -19,3 +19,8 @@ Generate javadoc ``` ./gradlew javadoc ``` + +Create maven POM file: +``` +./gradlew generatePomFileForMavenJavaPublication +``` \ No newline at end of file diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 109a47227..aab643d36 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -8,10 +8,12 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' + id 'maven-publish' + // id 'signing' } group 'com.ibm.able' -version '1.0.0-beta-1' +version '1.0.0-beta-2' archivesBaseName = 'accessibility-checker' repositories { @@ -59,4 +61,44 @@ jar { } duplicatesStrategy = DuplicatesStrategy.INCLUDE -} \ No newline at end of file +} + +publishing { + repositories { + maven { + name = "GitHubPackages" + url = uri("https://maven.pkg.github.com/IBMa/equal-access") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") + password = project.findProperty("gpr.key") ?: System.getenv("TOKEN") + } + } + } + publications { + githubJava(MavenPublication) { + from components.java + artifactId = 'accessibility-checker' + + pom { + name = 'accessibility-checker' + description = 'A module that allows you to perform integrated accessibility testing for environments such as JUnit and Selenium' + url = 'https://www.ibm.com/able/toolkit/tools/' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + scm { + connection = 'scm:git:git://github.com/IBMa/equal-access.git' + developerConnection = 'scm:git:ssh://github.com/IBMa/equal-access.git' + url = 'https://github.com/IBMa/equal-access' + } + } + } + } +} + +// signing { +// sign publishing.publications.githubJava +// } \ No newline at end of file From 92e73abab845d8a967f7e0e20523f8159f4ca0f5 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 13:44:51 -0500 Subject: [PATCH 031/161] yaml syntax --- .github/workflows/test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b8744d426..6295bf7bb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -418,10 +418,10 @@ jobs: chromedriverpath: ${{ steps.setup-chrome.outputs.chromedriver-path }} chromebinpath: ${{ steps.setup-chrome.outputs.chrome-path }} - name: Publish to GitHub Packages - run: gradle publish - env: - USERNAME: ${{ github.actor }} - PASSWORD: ${{ secrets.GITHUB_TOKEN }} + run: gradle publish + env: + USERNAME: ${{ github.actor }} + PASSWORD: ${{ secrets.GITHUB_TOKEN }} ############################################################################### # Karma Tests From cdaa7e3c82165dc4300659683bb7faaf05f2b9ea Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 13:46:50 -0500 Subject: [PATCH 032/161] working directory --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6295bf7bb..3897052d1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -419,6 +419,7 @@ jobs: chromebinpath: ${{ steps.setup-chrome.outputs.chrome-path }} - name: Publish to GitHub Packages run: gradle publish + working-directory: java-accessibility-checker env: USERNAME: ${{ github.actor }} PASSWORD: ${{ secrets.GITHUB_TOKEN }} From 577b31c5390e4b043a44553834ed397519aa8600 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 14:06:39 -0500 Subject: [PATCH 033/161] Generate pom --- .github/workflows/test.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3897052d1..04b0cf068 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -414,9 +414,8 @@ jobs: java-version: '17' - run: ./gradlew jar working-directory: java-accessibility-checker - env: - chromedriverpath: ${{ steps.setup-chrome.outputs.chromedriver-path }} - chromebinpath: ${{ steps.setup-chrome.outputs.chrome-path }} + - run: ./gradlew generatePomFileForMavenJavaPublication + working-directory: java-accessibility-checker - name: Publish to GitHub Packages run: gradle publish working-directory: java-accessibility-checker From f7b122bfd7c1433323b9db530da0c56dcf146b95 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 14:10:23 -0500 Subject: [PATCH 034/161] package write --- .github/workflows/test.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 04b0cf068..187dc3d29 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -401,7 +401,8 @@ jobs: #### java-accessibility-checker-buildtest: runs-on: ubuntu-22.04 - + permissions: + packages: write strategy: matrix: node-version: [18.x] @@ -414,8 +415,6 @@ jobs: java-version: '17' - run: ./gradlew jar working-directory: java-accessibility-checker - - run: ./gradlew generatePomFileForMavenJavaPublication - working-directory: java-accessibility-checker - name: Publish to GitHub Packages run: gradle publish working-directory: java-accessibility-checker From 2f96ca1ed2729643874098d27ef2049aa7004f4a Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 14:19:48 -0500 Subject: [PATCH 035/161] switch token --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 187dc3d29..f06a38d06 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -419,8 +419,8 @@ jobs: run: gradle publish working-directory: java-accessibility-checker env: - USERNAME: ${{ github.actor }} - PASSWORD: ${{ secrets.GITHUB_TOKEN }} + USERNAME: ${{ secrets.MVN_GITHUB_USER }} + PASSWORD: ${{ secrets.MVN_GITHUB_TOKEN }} ############################################################################### # Karma Tests From 33622449b8dd5a04a0663780d2dd5055422efb49 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 14:21:46 -0500 Subject: [PATCH 036/161] Generate pom --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f06a38d06..7f8490ab3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -415,6 +415,8 @@ jobs: java-version: '17' - run: ./gradlew jar working-directory: java-accessibility-checker + - run: ./gradlew generatePomFileForGithubJavaPublication + working-directory: java-accessibility-checker - name: Publish to GitHub Packages run: gradle publish working-directory: java-accessibility-checker From d4e666f8aab597261098b810ed8b6af80ded7076 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 14:25:18 -0500 Subject: [PATCH 037/161] Wrong gradle? --- .github/workflows/test.yml | 2 +- java-accessibility-checker/lib/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7f8490ab3..1fe5d3acb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -418,7 +418,7 @@ jobs: - run: ./gradlew generatePomFileForGithubJavaPublication working-directory: java-accessibility-checker - name: Publish to GitHub Packages - run: gradle publish + run: ./gradlew publish working-directory: java-accessibility-checker env: USERNAME: ${{ secrets.MVN_GITHUB_USER }} diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index aab643d36..6b807ac27 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -13,7 +13,7 @@ plugins { } group 'com.ibm.able' -version '1.0.0-beta-2' +version '1.0.0-beta-3' archivesBaseName = 'accessibility-checker' repositories { From b798cccbc226dda3d9416360f4f304afcf2151f9 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 14:31:51 -0500 Subject: [PATCH 038/161] creds --- java-accessibility-checker/lib/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 6b807ac27..2e1d66719 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -69,8 +69,8 @@ publishing { name = "GitHubPackages" url = uri("https://maven.pkg.github.com/IBMa/equal-access") credentials { - username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") - password = project.findProperty("gpr.key") ?: System.getenv("TOKEN") + username = project.findProperty("githubJava.user") ?: System.getenv("USERNAME") + password = project.findProperty("githubJava.key") ?: System.getenv("TOKEN") } } } From eafb554232e9dc63a4fe7a623eed640608075cfa Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 14:48:26 -0500 Subject: [PATCH 039/161] Add boilerplate --- .../junit-selenium/.gitattributes | 12 + .../boilerplates/junit-selenium/.gitignore | 5 + .../junit-selenium/gradle/libs.versions.toml | 12 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43504 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../boilerplates/junit-selenium/gradlew | 252 ++++++++++++++++++ .../boilerplates/junit-selenium/gradlew.bat | 94 +++++++ .../junit-selenium/lib/.gitignore | 1 + .../junit-selenium/lib/build.gradle | 56 ++++ .../lib/src/main/java/com/foo/SomeClass.java | 23 ++ .../src/test/java/com/foo/SomeClassTest.java | 72 +++++ .../junit-selenium/settings.gradle | 14 + .../ibm/able/report/ACReporterMetrics.java | 1 - 13 files changed, 548 insertions(+), 1 deletion(-) create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/.gitattributes create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/.gitignore create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/gradle/libs.versions.toml create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/gradle/wrapper/gradle-wrapper.jar create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/gradle/wrapper/gradle-wrapper.properties create mode 100755 java-accessibility-checker/boilerplates/junit-selenium/gradlew create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/gradlew.bat create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/lib/.gitignore create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/lib/src/main/java/com/foo/SomeClass.java create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java create mode 100644 java-accessibility-checker/boilerplates/junit-selenium/settings.gradle diff --git a/java-accessibility-checker/boilerplates/junit-selenium/.gitattributes b/java-accessibility-checker/boilerplates/junit-selenium/.gitattributes new file mode 100644 index 000000000..f91f64602 --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/.gitattributes @@ -0,0 +1,12 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + +# Binary files should be left untouched +*.jar binary + diff --git a/java-accessibility-checker/boilerplates/junit-selenium/.gitignore b/java-accessibility-checker/boilerplates/junit-selenium/.gitignore new file mode 100644 index 000000000..1b6985c00 --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/.gitignore @@ -0,0 +1,5 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/java-accessibility-checker/boilerplates/junit-selenium/gradle/libs.versions.toml b/java-accessibility-checker/boilerplates/junit-selenium/gradle/libs.versions.toml new file mode 100644 index 000000000..ab0036d1b --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/gradle/libs.versions.toml @@ -0,0 +1,12 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format + +[versions] +commons-math3 = "3.6.1" +guava = "33.1.0-jre" +junit = "4.13.2" + +[libraries] +commons-math3 = { module = "org.apache.commons:commons-math3", version.ref = "commons-math3" } +guava = { module = "com.google.guava:guava", version.ref = "guava" } +junit = { module = "junit:junit", version.ref = "junit" } diff --git a/java-accessibility-checker/boilerplates/junit-selenium/gradle/wrapper/gradle-wrapper.jar b/java-accessibility-checker/boilerplates/junit-selenium/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2c3521197d7c4586c843d1d3e9090525f1898cde GIT binary patch literal 43504 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 TZiJi*F`$tkWLn) literal 0 HcmV?d00001 diff --git a/java-accessibility-checker/boilerplates/junit-selenium/gradle/wrapper/gradle-wrapper.properties b/java-accessibility-checker/boilerplates/junit-selenium/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..09523c0e5 --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/java-accessibility-checker/boilerplates/junit-selenium/gradlew b/java-accessibility-checker/boilerplates/junit-selenium/gradlew new file mode 100755 index 000000000..f5feea6d6 --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/java-accessibility-checker/boilerplates/junit-selenium/gradlew.bat b/java-accessibility-checker/boilerplates/junit-selenium/gradlew.bat new file mode 100644 index 000000000..9d21a2183 --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/.gitignore b/java-accessibility-checker/boilerplates/junit-selenium/lib/.gitignore new file mode 100644 index 000000000..872aa273a --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/.gitignore @@ -0,0 +1 @@ +results \ No newline at end of file diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle new file mode 100644 index 000000000..b3fde3520 --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle @@ -0,0 +1,56 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.9/userguide/building_java_projects.html in the Gradle documentation. + */ + +plugins { + id 'java-library' +} + +group 'com.foo' +version '1.0.0' + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() + maven { + url = uri("https://maven.pkg.github.com/IBMa/equal-access") + credentials { + username = project.findProperty("gpr.user") ?: System.getenv("USERNAME") + password = project.findProperty("gpr.key") ?: System.getenv("TOKEN") + } + } +} + +dependencies { + // Use JUnit test framework. + testImplementation libs.junit + + // This dependency is exported to consumers, that is to say found on their compile classpath. + api libs.commons.math3 + + // This dependency is used internally, and not exposed to consumers on their own compile classpath. + implementation libs.guava + + // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java + implementation 'org.seleniumhq.selenium:selenium-java:4.23.0' + implementation 'com.google.code.gson:gson:2.11.0' + // https://mavenlibs.com/maven/dependency/org.mozilla/rhino + implementation 'org.mozilla:rhino:1.7.14' + implementation 'com.ibm.able:accessibility-checker:1.0.0-beta-2' +} + +// Apply a specific Java toolchain to ease working on different environments. +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +test { + testLogging { + showStandardStreams = true + } +} diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/src/main/java/com/foo/SomeClass.java b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/main/java/com/foo/SomeClass.java new file mode 100644 index 000000000..e6fae59ed --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/main/java/com/foo/SomeClass.java @@ -0,0 +1,23 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.foo; + +public class SomeClass { + + public boolean someFunction() { + return true; + } +} diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java new file mode 100644 index 000000000..33101e998 --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java @@ -0,0 +1,72 @@ +/****************************************************************************** + Copyright:: 2024- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +package com.ibm.able; + +import org.junit.Test; +import static org.junit.Assert.*; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.openqa.selenium.SessionNotCreatedException; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; + +import com.ibm.able.engine.ACReport; +import com.ibm.able.engine.ACReport.Result; +import com.ibm.able.report.BaselineManager.eAssertResult; + +public class SomeClassTest { + private static ChromeDriver driver; + + /** + * Setup a Selenium Chrome environment before tests + */ + @BeforeClass public static void setup() { + String workingDir = System.getProperty("user.dir"); + String chromeDriverDir = System.getenv("chromedriverpath"); + ChromeOptions options = new ChromeOptions(); + if (chromeDriverDir == null) { + chromeDriverDir = workingDir+"/src/test/resources/chromedriver-mac-arm64/chromedriver"; + } else { + options.setBinary(System.getenv("chromebinpath")); + } + System.setProperty("webdriver.chrome.driver", chromeDriverDir); + options.addArguments("--headless=new"); + try { + SomeClassTest.driver = new ChromeDriver(options); + } catch (SessionNotCreatedException e) { + System.out.println(e.getMessage()); + System.out.println(e.getAdditionalInformation()); + throw e; + } + } + + /** + * Close Selenium Chrome environment after tests + */ + @AfterClass public static void teardown() { + SomeClassTest.driver.close(); + AccessibilityChecker.close(); + } + + @Test public void getCompliance() { + SomeClassTest.driver.get("https://altoromutual.12mc9fdq8fib.us-south.codeengine.appdomain.cloud/"); + + ACReport report = AccessibilityChecker.getCompliance(driver, "getComplianceTest"); + eAssertResult resultCode = AccessibilityChecker.assertCompliance(report); + assertEquals(resultCode, eAssertResult.PASS); + } +} diff --git a/java-accessibility-checker/boilerplates/junit-selenium/settings.gradle b/java-accessibility-checker/boilerplates/junit-selenium/settings.gradle new file mode 100644 index 000000000..9e57c289e --- /dev/null +++ b/java-accessibility-checker/boilerplates/junit-selenium/settings.gradle @@ -0,0 +1,14 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.9/userguide/multi_project_builds.html in the Gradle documentation. + */ + +plugins { + // Apply the foojay-resolver plugin to allow automatic download of JDKs + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' +} + +rootProject.name = 'java-accessibility-checker-boilerplate-selenium' +include('lib') diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java index 00f2a32f1..7aad2dd3a 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java @@ -88,7 +88,6 @@ public ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, // Dispatch the call to the metrics server try { - System.out.println(this.metricsURLV2 + "/api/pub/meter/v2" + qs.toString()); Fetch.get(this.metricsURLV2 + "/api/pub/meter/v2" + qs.toString()); } catch (Throwable t) { System.err.println(t); From e9fe1d1e43f6c8f0cd1de97fa98d1a936a64fc73 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 15:26:29 -0500 Subject: [PATCH 040/161] Move files into equalaccess sub namespace --- java-accessibility-checker/README-DEV.md | 2 +- .../junit-selenium/lib/build.gradle | 2 +- .../src/test/java/com/foo/SomeClassTest.java | 8 ++--- java-accessibility-checker/lib/build.gradle | 2 +- .../AccessibilityChecker.java | 32 +++++++++---------- .../{ => equalaccess}/abs/IAbstractAPI.java | 4 +-- .../ibm/able/{ => equalaccess}/abs/MyFS.java | 8 ++--- .../config/ACConfigManager.java | 6 ++-- .../{ => equalaccess}/config/Archive.java | 2 +- .../able/{ => equalaccess}/config/Config.java | 2 +- .../config/ConfigInternal.java | 2 +- .../{ => equalaccess}/engine/ACEReport.java | 2 +- .../{ => equalaccess}/engine/ACError.java | 2 +- .../{ => equalaccess}/engine/ACReport.java | 4 +-- .../engine/ACReportSummary.java | 8 ++--- .../able/{ => equalaccess}/engine/Bounds.java | 2 +- .../{ => equalaccess}/engine/Guideline.java | 2 +- .../able/{ => equalaccess}/engine/Rule.java | 2 +- .../engine/eRuleConfidence.java | 2 +- .../{ => equalaccess}/engine/eRuleLevel.java | 2 +- .../enginecontext/EngineContextLocal.java | 14 ++++---- .../enginecontext/EngineContextManager.java | 4 +-- .../enginecontext/EngineContextSelenium.java | 18 +++++------ .../enginecontext/IEngineContext.java | 8 ++--- .../report/ACReporterJSON.java | 12 +++---- .../report/ACReporterMetrics.java | 10 +++--- .../report/BaselineManager.java | 12 +++---- .../report/CompressedReport.java | 4 +-- .../{ => equalaccess}/report/IReporter.java | 6 ++-- .../report/ReporterFile.java | 2 +- .../report/ReporterManager.java | 20 ++++++------ .../report/ReporterStored.java | 4 +-- .../able/{ => equalaccess}/util/Fetch.java | 2 +- .../ibm/able/{ => equalaccess}/util/Misc.java | 2 +- .../AccessibilityCheckerTest.java | 10 +++--- .../config/ACConfigManagerTest.java | 2 +- .../engine/ACReportTest.java | 4 +-- .../{ => equalaccess}/util/FetchTest.java | 4 +-- 38 files changed, 117 insertions(+), 117 deletions(-) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/AccessibilityChecker.java (89%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/abs/IAbstractAPI.java (91%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/abs/MyFS.java (92%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/config/ACConfigManager.java (99%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/config/Archive.java (96%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/config/Config.java (98%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/config/ConfigInternal.java (98%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/engine/ACEReport.java (98%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/engine/ACError.java (95%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/engine/ACReport.java (99%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/engine/ACReportSummary.java (94%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/engine/Bounds.java (96%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/engine/Guideline.java (96%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/engine/Rule.java (95%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/engine/eRuleConfidence.java (96%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/engine/eRuleLevel.java (96%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/enginecontext/EngineContextLocal.java (91%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/enginecontext/EngineContextManager.java (95%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/enginecontext/EngineContextSelenium.java (94%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/enginecontext/IEngineContext.java (84%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/report/ACReporterJSON.java (88%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/report/ACReporterMetrics.java (94%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/report/BaselineManager.java (97%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/report/CompressedReport.java (98%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/report/IReporter.java (88%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/report/ReporterFile.java (96%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/report/ReporterManager.java (95%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/report/ReporterStored.java (92%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/util/Fetch.java (99%) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/{ => equalaccess}/util/Misc.java (97%) rename java-accessibility-checker/lib/src/test/java/com/ibm/able/{ => equalaccess}/AccessibilityCheckerTest.java (97%) rename java-accessibility-checker/lib/src/test/java/com/ibm/able/{ => equalaccess}/config/ACConfigManagerTest.java (99%) rename java-accessibility-checker/lib/src/test/java/com/ibm/able/{ => equalaccess}/engine/ACReportTest.java (94%) rename java-accessibility-checker/lib/src/test/java/com/ibm/able/{ => equalaccess}/util/FetchTest.java (93%) diff --git a/java-accessibility-checker/README-DEV.md b/java-accessibility-checker/README-DEV.md index 2c235c24c..ef76cd2a9 100644 --- a/java-accessibility-checker/README-DEV.md +++ b/java-accessibility-checker/README-DEV.md @@ -2,7 +2,7 @@ Run a specific testcase: ``` -./gradlew test --tests com.ibm.able.AccessibilityCheckerTest +./gradlew test --tests com.ibm.able.equalaccess.AccessibilityCheckerTest ``` Run all tests: diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle index b3fde3520..b5dcf0d33 100644 --- a/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle @@ -39,7 +39,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.11.0' // https://mavenlibs.com/maven/dependency/org.mozilla/rhino implementation 'org.mozilla:rhino:1.7.14' - implementation 'com.ibm.able:accessibility-checker:1.0.0-beta-2' + implementation 'com.ibm.able.equalaccess:accessibility-checker:1.0.0-beta-2' } // Apply a specific Java toolchain to ease working on different environments. diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java index 33101e998..af0dadd78 100644 --- a/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able; +package com.foo; import org.junit.Test; import static org.junit.Assert.*; @@ -24,9 +24,9 @@ import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; -import com.ibm.able.engine.ACReport; -import com.ibm.able.engine.ACReport.Result; -import com.ibm.able.report.BaselineManager.eAssertResult; +import com.ibm.able.equalaccess.engine.ACReport; +import com.ibm.able.equalaccess.engine.ACReport.Result; +import com.ibm.able.equalaccess.report.BaselineManager.eAssertResult; public class SomeClassTest { private static ChromeDriver driver; diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 2e1d66719..5aff8a1f0 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -12,7 +12,7 @@ plugins { // id 'signing' } -group 'com.ibm.able' +group 'com.ibm.able.equalaccess' version '1.0.0-beta-3' archivesBaseName = 'accessibility-checker' diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/AccessibilityChecker.java similarity index 89% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/AccessibilityChecker.java index 5a3bdae7b..aabeee5ef 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/AccessibilityChecker.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/AccessibilityChecker.java @@ -13,27 +13,27 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able; +package com.ibm.able.equalaccess; import java.util.Date; import java.util.HashMap; import java.util.Map; -import com.ibm.able.config.ACConfigManager; -import com.ibm.able.config.Config; -import com.ibm.able.config.ConfigInternal; -import com.ibm.able.engine.ACEReport; -import com.ibm.able.engine.ACReport; -import com.ibm.able.engine.Guideline; -import com.ibm.able.engine.Rule; -import com.ibm.able.enginecontext.EngineContextManager; -import com.ibm.able.enginecontext.IEngineContext; -import com.ibm.able.report.BaselineManager; -import com.ibm.able.report.ReporterManager; -import com.ibm.able.report.BaselineManager.DiffResult; -import com.ibm.able.report.BaselineManager.eAssertResult; -import com.ibm.able.abs.IAbstractAPI; -import com.ibm.able.abs.MyFS; +import com.ibm.able.equalaccess.config.ACConfigManager; +import com.ibm.able.equalaccess.config.Config; +import com.ibm.able.equalaccess.config.ConfigInternal; +import com.ibm.able.equalaccess.engine.ACEReport; +import com.ibm.able.equalaccess.engine.ACReport; +import com.ibm.able.equalaccess.engine.Guideline; +import com.ibm.able.equalaccess.engine.Rule; +import com.ibm.able.equalaccess.enginecontext.EngineContextManager; +import com.ibm.able.equalaccess.enginecontext.IEngineContext; +import com.ibm.able.equalaccess.report.BaselineManager; +import com.ibm.able.equalaccess.report.ReporterManager; +import com.ibm.able.equalaccess.report.BaselineManager.DiffResult; +import com.ibm.able.equalaccess.report.BaselineManager.eAssertResult; +import com.ibm.able.equalaccess.abs.IAbstractAPI; +import com.ibm.able.equalaccess.abs.MyFS; public class AccessibilityChecker { private AccessibilityChecker() {} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/IAbstractAPI.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/IAbstractAPI.java similarity index 91% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/IAbstractAPI.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/IAbstractAPI.java index 021daab86..0808d5ea8 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/IAbstractAPI.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/IAbstractAPI.java @@ -13,11 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.abs; +package com.ibm.able.equalaccess.abs; import java.io.IOException; -import com.ibm.able.engine.ACReport; +import com.ibm.able.equalaccess.engine.ACReport; public interface IAbstractAPI { public ACReport loadBaseline(String scanLabel); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/MyFS.java similarity index 92% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/MyFS.java index 0bea28638..a0237e697 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/abs/MyFS.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/MyFS.java @@ -13,9 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.abs; +package com.ibm.able.equalaccess.abs; -import com.ibm.able.engine.ACReport; +import com.ibm.able.equalaccess.engine.ACReport; import java.io.File; import java.io.FileNotFoundException; @@ -27,8 +27,8 @@ import com.google.gson.Gson; import com.google.gson.stream.JsonReader; -import com.ibm.able.config.ACConfigManager; -import com.ibm.able.config.ConfigInternal; +import com.ibm.able.equalaccess.config.ACConfigManager; +import com.ibm.able.equalaccess.config.ConfigInternal; public class MyFS implements IAbstractAPI { public static Gson gson = new Gson(); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ACConfigManager.java similarity index 99% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ACConfigManager.java index 7d116ad00..5b4d1aafb 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ACConfigManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ACConfigManager.java @@ -14,7 +14,7 @@ limitations under the License. *****************************************************************************/ -package com.ibm.able.config; +package com.ibm.able.equalaccess.config; import java.io.FileNotFoundException; import java.io.FileReader; @@ -26,8 +26,8 @@ import com.google.gson.Gson; import com.google.gson.stream.JsonReader; -import com.ibm.able.util.Fetch; -import com.ibm.able.util.Misc; +import com.ibm.able.equalaccess.util.Fetch; +import com.ibm.able.equalaccess.util.Misc; public class ACConfigManager { private static class ConfigError extends Error { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Archive.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/Archive.java similarity index 96% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Archive.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/Archive.java index 95243730a..9d44348f1 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Archive.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/Archive.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.config; +package com.ibm.able.equalaccess.config; import java.util.HashMap; import java.util.Map; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/Config.java similarity index 98% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/Config.java index 159f9e334..7747d03fb 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/Config.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/Config.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.config; +package com.ibm.able.equalaccess.config; public class Config { Config() {} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ConfigInternal.java similarity index 98% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ConfigInternal.java index c72421e8e..02adcaadf 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/config/ConfigInternal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ConfigInternal.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.config; +package com.ibm.able.equalaccess.config; import java.nio.file.Paths; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java similarity index 98% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java index 8c071bd2c..77eddea40 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACEReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java @@ -14,7 +14,7 @@ limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; import java.util.Map; public class ACEReport { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACError.java similarity index 95% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACError.java index a6eb1f063..004773357 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACError.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACError.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; public class ACError extends Error { public ACError(String msg) { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java similarity index 99% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java index c9258e5ab..555aa880f 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java @@ -14,7 +14,7 @@ limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -23,7 +23,7 @@ import java.util.Set; import java.util.stream.Stream; -import com.ibm.able.config.ConfigInternal; +import com.ibm.able.equalaccess.config.ConfigInternal; public class ACReport implements Cloneable { public static class SummaryCounts implements Cloneable { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java similarity index 94% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java index 18ac21235..412e8517a 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/ACReportSummary.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java @@ -14,7 +14,7 @@ limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -22,9 +22,9 @@ import java.util.Set; import java.util.Map.Entry; -import com.ibm.able.config.ConfigInternal; -import com.ibm.able.report.CompressedReport; -import com.ibm.able.report.ReporterStored; +import com.ibm.able.equalaccess.config.ConfigInternal; +import com.ibm.able.equalaccess.report.CompressedReport; +import com.ibm.able.equalaccess.report.ReporterStored; public class ACReportSummary { public static class SummaryCounts { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Bounds.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/Bounds.java similarity index 96% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Bounds.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/Bounds.java index 79517a88a..9f41fac6f 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Bounds.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/Bounds.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; public class Bounds implements Cloneable { int top = -1; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Guideline.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/Guideline.java similarity index 96% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Guideline.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/Guideline.java index 76f1fa0e4..06e581717 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Guideline.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/Guideline.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; public class Guideline { public static class Rule { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Rule.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/Rule.java similarity index 95% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Rule.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/Rule.java index 3d0c482e6..0620d2f57 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/Rule.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/Rule.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; import java.util.Map; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/eRuleConfidence.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/eRuleConfidence.java similarity index 96% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/eRuleConfidence.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/eRuleConfidence.java index f376b73d2..c19ed4aa4 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/eRuleConfidence.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/eRuleConfidence.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; public enum eRuleConfidence { PASS("PASS"), diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/eRuleLevel.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/eRuleLevel.java similarity index 96% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/eRuleLevel.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/eRuleLevel.java index 2e5435020..2d022db39 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/engine/eRuleLevel.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/eRuleLevel.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; public enum eRuleLevel { violation("violation"), diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java similarity index 91% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java index 443c06d24..5e3582ed6 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextLocal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java @@ -13,16 +13,16 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.enginecontext; +package com.ibm.able.equalaccess.enginecontext; import java.io.IOException; import com.google.gson.Gson; -import com.ibm.able.config.ACConfigManager; -import com.ibm.able.config.ConfigInternal; -import com.ibm.able.engine.ACEReport; -import com.ibm.able.engine.Guideline; -import com.ibm.able.engine.Rule; -import com.ibm.able.util.Fetch; +import com.ibm.able.equalaccess.config.ACConfigManager; +import com.ibm.able.equalaccess.config.ConfigInternal; +import com.ibm.able.equalaccess.engine.ACEReport; +import com.ibm.able.equalaccess.engine.Guideline; +import com.ibm.able.equalaccess.engine.Rule; +import com.ibm.able.equalaccess.util.Fetch; import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java similarity index 95% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java index e824eaedd..8f949f314 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java @@ -13,13 +13,13 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.enginecontext; +package com.ibm.able.equalaccess.enginecontext; import java.io.IOException; import org.openqa.selenium.WebDriver; -import com.ibm.able.util.Misc; +import com.ibm.able.equalaccess.util.Misc; public class EngineContextManager { private EngineContextManager() {} diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextSelenium.java similarity index 94% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextSelenium.java index 2962ff982..608db3a46 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/EngineContextSelenium.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextSelenium.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.enginecontext; +package com.ibm.able.equalaccess.enginecontext; import java.io.IOException; import java.time.Duration; @@ -25,14 +25,14 @@ import org.openqa.selenium.WebDriver; import com.google.gson.Gson; -import com.ibm.able.config.ACConfigManager; -import com.ibm.able.config.Config; -import com.ibm.able.config.ConfigInternal; -import com.ibm.able.engine.ACError; -import com.ibm.able.engine.Guideline; -import com.ibm.able.engine.Rule; -import com.ibm.able.engine.ACEReport; -import com.ibm.able.util.Fetch; +import com.ibm.able.equalaccess.config.ACConfigManager; +import com.ibm.able.equalaccess.config.Config; +import com.ibm.able.equalaccess.config.ConfigInternal; +import com.ibm.able.equalaccess.engine.ACError; +import com.ibm.able.equalaccess.engine.Guideline; +import com.ibm.able.equalaccess.engine.Rule; +import com.ibm.able.equalaccess.engine.ACEReport; +import com.ibm.able.equalaccess.util.Fetch; public class EngineContextSelenium implements IEngineContext { private static Gson gson = new Gson(); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java similarity index 84% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java index 9fb7e67f3..dac3d8e2a 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/enginecontext/IEngineContext.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java @@ -13,13 +13,13 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.enginecontext; +package com.ibm.able.equalaccess.enginecontext; import java.io.IOException; -import com.ibm.able.engine.ACEReport; -import com.ibm.able.engine.Guideline; -import com.ibm.able.engine.Rule; +import com.ibm.able.equalaccess.engine.ACEReport; +import com.ibm.able.equalaccess.engine.Guideline; +import com.ibm.able.equalaccess.engine.Rule; public interface IEngineContext { public void loadEngine() throws IOException; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterJSON.java similarity index 88% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterJSON.java index 9da2aa017..c4597f6eb 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterJSON.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterJSON.java @@ -13,17 +13,17 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.report; +package com.ibm.able.equalaccess.report; import java.util.Date; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.ibm.able.config.ConfigInternal; -import com.ibm.able.engine.ACReport; -import com.ibm.able.engine.ACReportSummary; -import com.ibm.able.engine.Guideline; -import com.ibm.able.util.Misc; +import com.ibm.able.equalaccess.config.ConfigInternal; +import com.ibm.able.equalaccess.engine.ACReport; +import com.ibm.able.equalaccess.engine.ACReportSummary; +import com.ibm.able.equalaccess.engine.Guideline; +import com.ibm.able.equalaccess.util.Misc; public class ACReporterJSON implements IReporter { private static Gson gson = new GsonBuilder().setPrettyPrinting().create(); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java similarity index 94% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java index 7aad2dd3a..d5a664155 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ACReporterMetrics.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.report; +package com.ibm.able.equalaccess.report; import java.util.Arrays; import java.util.HashMap; @@ -22,10 +22,10 @@ import java.util.Map; import java.util.Map.Entry; -import com.ibm.able.config.ConfigInternal; -import com.ibm.able.engine.Guideline; -import com.ibm.able.enginecontext.EngineContextManager; -import com.ibm.able.util.Fetch; +import com.ibm.able.equalaccess.config.ConfigInternal; +import com.ibm.able.equalaccess.engine.Guideline; +import com.ibm.able.equalaccess.enginecontext.EngineContextManager; +import com.ibm.able.equalaccess.util.Fetch; /******************************************************************************* * NAME: ACMetricsLogger.js diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/BaselineManager.java similarity index 97% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/BaselineManager.java index 179547ee8..0b2f7673f 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/BaselineManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/BaselineManager.java @@ -14,7 +14,7 @@ limitations under the License. *****************************************************************************/ -package com.ibm.able.report; +package com.ibm.able.equalaccess.report; import java.util.ArrayList; import java.util.Arrays; @@ -23,11 +23,11 @@ import java.util.stream.Stream; import com.google.gson.Gson; -import com.ibm.able.abs.IAbstractAPI; -import com.ibm.able.config.ConfigInternal; -import com.ibm.able.engine.ACReport; -import com.ibm.able.engine.ACReport.Result; -import com.ibm.able.engine.Rule; +import com.ibm.able.equalaccess.abs.IAbstractAPI; +import com.ibm.able.equalaccess.config.ConfigInternal; +import com.ibm.able.equalaccess.engine.ACReport; +import com.ibm.able.equalaccess.engine.ACReport.Result; +import com.ibm.able.equalaccess.engine.Rule; /** * This interface is responsible for aChecker baselines and comparing scans to baselines diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java similarity index 98% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java index 0c36b19a1..b65fb0136 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/CompressedReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java @@ -13,12 +13,12 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.report; +package com.ibm.able.equalaccess.report; import java.util.HashMap; import java.util.Map; -import com.ibm.able.engine.ACReport; +import com.ibm.able.equalaccess.engine.ACReport; public class CompressedReport { public static String scanID; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/IReporter.java similarity index 88% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/IReporter.java index cda60734c..95c5ed20a 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/IReporter.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/IReporter.java @@ -13,10 +13,10 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.report; +package com.ibm.able.equalaccess.report; -import com.ibm.able.config.ConfigInternal; -import com.ibm.able.engine.Guideline; +import com.ibm.able.equalaccess.config.ConfigInternal; +import com.ibm.able.equalaccess.engine.Guideline; public interface IReporter { String name(); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterFile.java similarity index 96% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterFile.java index bc5895324..755138527 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterFile.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterFile.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.report; +package com.ibm.able.equalaccess.report; public class ReporterFile { public String path; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java similarity index 95% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java index e53c08f1b..683008c5a 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.report; +package com.ibm.able.equalaccess.report; import java.io.IOException; import java.util.ArrayList; @@ -26,15 +26,15 @@ import java.util.Set; import com.google.gson.Gson; -import com.ibm.able.abs.IAbstractAPI; -import com.ibm.able.config.ConfigInternal; -import com.ibm.able.engine.ACEReport; -import com.ibm.able.engine.ACError; -import com.ibm.able.engine.ACReport; -import com.ibm.able.engine.Guideline; -import com.ibm.able.engine.eRuleConfidence; -import com.ibm.able.engine.eRuleLevel; -import com.ibm.able.engine.ACReport.Result; +import com.ibm.able.equalaccess.abs.IAbstractAPI; +import com.ibm.able.equalaccess.config.ConfigInternal; +import com.ibm.able.equalaccess.engine.ACEReport; +import com.ibm.able.equalaccess.engine.ACError; +import com.ibm.able.equalaccess.engine.ACReport; +import com.ibm.able.equalaccess.engine.Guideline; +import com.ibm.able.equalaccess.engine.eRuleConfidence; +import com.ibm.able.equalaccess.engine.eRuleLevel; +import com.ibm.able.equalaccess.engine.ACReport.Result; public class ReporterManager { private static Gson gson = new Gson(); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterStored.java similarity index 92% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterStored.java index c093c05df..e95e29316 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/report/ReporterStored.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterStored.java @@ -13,9 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.report; +package com.ibm.able.equalaccess.report; -import com.ibm.able.engine.ACReport; +import com.ibm.able.equalaccess.engine.ACReport; public class ReporterStored { public String pageTitle; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/util/Fetch.java similarity index 99% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/util/Fetch.java index 45b7ed982..c8b8f002a 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Fetch.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/util/Fetch.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.util; +package com.ibm.able.equalaccess.util; import java.io.BufferedReader; import java.io.IOException; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/util/Misc.java similarity index 97% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/util/Misc.java index e8b59a7ff..6f479c7c9 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/util/Misc.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/util/Misc.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.util; +package com.ibm.able.equalaccess.util; import java.text.DateFormat; import java.text.SimpleDateFormat; diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java similarity index 97% rename from java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java rename to java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java index 5a730da9e..e882adb59 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able; +package com.ibm.able.equalaccess; import org.junit.Test; import static org.junit.Assert.*; @@ -38,10 +38,10 @@ import com.google.common.io.Files; import com.google.gson.Gson; -import com.ibm.able.config.ACConfigManager; -import com.ibm.able.engine.ACReport; -import com.ibm.able.engine.ACReport.Result; -import com.ibm.able.report.BaselineManager.eAssertResult; +import com.ibm.able.equalaccess.config.ACConfigManager; +import com.ibm.able.equalaccess.engine.ACReport; +import com.ibm.able.equalaccess.engine.ACReport.Result; +import com.ibm.able.equalaccess.report.BaselineManager.eAssertResult; public class AccessibilityCheckerTest { public static class UnitTestInfoResult { diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/config/ACConfigManagerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/config/ACConfigManagerTest.java similarity index 99% rename from java-accessibility-checker/lib/src/test/java/com/ibm/able/config/ACConfigManagerTest.java rename to java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/config/ACConfigManagerTest.java index c152c2619..c22d8b7e2 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/config/ACConfigManagerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/config/ACConfigManagerTest.java @@ -14,7 +14,7 @@ limitations under the License. *****************************************************************************/ -package com.ibm.able.config; +package com.ibm.able.equalaccess.config; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/engine/ACReportTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/engine/ACReportTest.java similarity index 94% rename from java-accessibility-checker/lib/src/test/java/com/ibm/able/engine/ACReportTest.java rename to java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/engine/ACReportTest.java index 371a12422..3d7d8f100 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/engine/ACReportTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/engine/ACReportTest.java @@ -13,12 +13,12 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.engine; +package com.ibm.able.equalaccess.engine; import org.junit.Test; import static org.junit.Assert.*; -import com.ibm.able.engine.ACReport; +import com.ibm.able.equalaccess.engine.ACReport; public class ACReportTest { diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/util/FetchTest.java similarity index 93% rename from java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java rename to java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/util/FetchTest.java index 3929d6e57..c9882d5bf 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/util/FetchTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/util/FetchTest.java @@ -13,14 +13,14 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.util; +package com.ibm.able.equalaccess.util; import org.junit.Test; import static org.junit.Assert.*; import java.io.IOException; -import com.ibm.able.util.Fetch; +import com.ibm.able.equalaccess.util.Fetch; public class FetchTest { @Test public void getArr() { From d4488175c615ed01bdd182d50e4fd2f8caf46005 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 15:28:14 -0500 Subject: [PATCH 041/161] Change boilerplate dependency version --- .../boilerplates/junit-selenium/lib/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle index b5dcf0d33..9fead409a 100644 --- a/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle @@ -39,7 +39,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.11.0' // https://mavenlibs.com/maven/dependency/org.mozilla/rhino implementation 'org.mozilla:rhino:1.7.14' - implementation 'com.ibm.able.equalaccess:accessibility-checker:1.0.0-beta-2' + implementation 'com.ibm.able.equalaccess:accessibility-checker:1.0.0-beta-3' } // Apply a specific Java toolchain to ease working on different environments. From ef779d9395da5f44792470114e836b9f32c6ef7b Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 13 Aug 2024 15:34:04 -0500 Subject: [PATCH 042/161] Flip expected, actual --- .../lib/src/test/java/com/foo/SomeClassTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java index af0dadd78..c04b93aca 100644 --- a/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java @@ -24,6 +24,7 @@ import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; +import com.ibm.able.equalaccess.AccessibilityChecker; import com.ibm.able.equalaccess.engine.ACReport; import com.ibm.able.equalaccess.engine.ACReport.Result; import com.ibm.able.equalaccess.report.BaselineManager.eAssertResult; @@ -67,6 +68,6 @@ public class SomeClassTest { ACReport report = AccessibilityChecker.getCompliance(driver, "getComplianceTest"); eAssertResult resultCode = AccessibilityChecker.assertCompliance(report); - assertEquals(resultCode, eAssertResult.PASS); + assertEquals(eAssertResult.PASS, resultCode); } } From 8ab315791ff30149930c101c6c24df043e694c57 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Wed, 14 Aug 2024 15:31:13 -0500 Subject: [PATCH 043/161] More isolation of selenium dependency --- .../junit-selenium/lib/build.gradle | 9 +- java-accessibility-checker/lib/build.gradle | 33 +++++- .../equalaccess/AccessibilityChecker.java | 2 +- .../equalaccess/config/ACConfigManager.java | 106 +++++++++--------- .../ibm/able/equalaccess/engine/ACReport.java | 3 +- .../equalaccess/engine/ACReportSummary.java | 6 - .../enginecontext/EngineContextLocal.java | 26 +++-- .../enginecontext/EngineContextManager.java | 32 +++++- .../enginecontext/IEngineContext.java | 7 ++ .../{ => selenium}/EngineContextSelenium.java | 21 +++- .../equalaccess/report/ACReporterMetrics.java | 8 +- .../equalaccess/report/BaselineManager.java | 1 - .../equalaccess/report/ReporterManager.java | 9 +- .../equalaccess/AccessibilityCheckerTest.java | 6 + .../config/ACConfigManagerTest.java | 14 ++- .../ibm/able/equalaccess/util/FetchTest.java | 2 - 16 files changed, 192 insertions(+), 93 deletions(-) rename java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/{ => selenium}/EngineContextSelenium.java (92%) diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle index 9fead409a..1a6a4d2fb 100644 --- a/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle @@ -36,11 +36,12 @@ dependencies { // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java implementation 'org.seleniumhq.selenium:selenium-java:4.23.0' - implementation 'com.google.code.gson:gson:2.11.0' - // https://mavenlibs.com/maven/dependency/org.mozilla/rhino - implementation 'org.mozilla:rhino:1.7.14' implementation 'com.ibm.able.equalaccess:accessibility-checker:1.0.0-beta-3' -} + implementation('com.ibm.able.equalaccess:accessibility-checker:1.0.0-beta-3') { + capabilities { + requireCapability("com.ibm.able.equalaccess:selenium") + } + }} // Apply a specific Java toolchain to ease working on different environments. java { diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 5aff8a1f0..44437ba39 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -16,6 +16,31 @@ group 'com.ibm.able.equalaccess' version '1.0.0-beta-3' archivesBaseName = 'accessibility-checker' +sourceSets { + selenium { + java { + srcDir 'src/main/java' + } + } + main { + java { + srcDir 'src/main/java' + exclude '**/enginecontext/selenium/**' + } + } + test { + java { + srcDir 'src/main/java' + } + } +} + +java { + registerFeature('selenium') { + usingSourceSet(sourceSets.selenium) + } +} + repositories { // Use Maven Central for resolving dependencies. mavenCentral() @@ -31,11 +56,14 @@ dependencies { // This dependency is used internally, and not exposed to consumers on their own compile classpath. implementation libs.guava - // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java - implementation 'org.seleniumhq.selenium:selenium-java:4.23.0' implementation 'com.google.code.gson:gson:2.11.0' // https://mavenlibs.com/maven/dependency/org.mozilla/rhino implementation 'org.mozilla:rhino:1.7.14' + + // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java + seleniumImplementation 'org.seleniumhq.selenium:selenium-java:4.23.0' + testImplementation 'org.seleniumhq.selenium:selenium-java:4.23.0' + // implementation 'org.seleniumhq.selenium:selenium-java:4.23.0' } // Apply a specific Java toolchain to ease working on different environments. @@ -48,6 +76,7 @@ java { test { testLogging { showStandardStreams = true + showStackTraces = true } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/AccessibilityChecker.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/AccessibilityChecker.java index aabeee5ef..b7c0f2ea4 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/AccessibilityChecker.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/AccessibilityChecker.java @@ -76,7 +76,7 @@ public static ACReport getCompliance(Object content, String label) { ACEReport origReport = engineContext.getCompliance(label); String url = engineContext.getUrl(); String title = engineContext.getTitle(); - ACReport finalReport = ReporterManager.get().addEngineReport("Selenium", startScan, url, title, label, origReport); + ACReport finalReport = ReporterManager.get().addEngineReport(engineContext.getProfile(), startScan, url, title, label, origReport); return finalReport; } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ACConfigManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ACConfigManager.java index 5b4d1aafb..102e1f5ac 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ACConfigManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/config/ACConfigManager.java @@ -30,6 +30,12 @@ import com.ibm.able.equalaccess.util.Misc; public class ACConfigManager { + public static final String ARCHIVE_LATEST = "latest"; + public static final String ARCHIVE_PREVIEW = "preview"; + public static final String ARCHIVE_VERSIONED = "versioned"; + + private ACConfigManager() {} + private static class ConfigError extends Error { ConfigError(String message) { super(message); @@ -37,18 +43,13 @@ private static class ConfigError extends Error { } - private static String[] covertPolicies(String policies) { - return policies.split(","); - } - - /** * negative if versionA is less than versionB, positive if versionA is greater than versionB, and zero if they are equal. NaN is treated as 0. * @param versionA * @param versionB */ public static int compareVersions(String versionA, String versionB) { - Pattern versionRE = Pattern.compile("[0-9.]+(-rc\\.[0-9]+)?"); + Pattern versionRE = Pattern.compile("[0-9.]+(-rc\\.[\\d]+)?"); versionA = versionA.trim(); versionB = versionB.trim(); if (!versionRE.matcher(versionA).matches()) throw new ConfigError("Invalid version"); @@ -89,7 +90,7 @@ public static int compareVersions(String versionA, String versionB) { * @param toolVersion */ private static String findLatestArchiveId(Archive[] archives, String toolVersion) { - String[] validArchiveKeywords = { "latest", "preview", "versioned" }; + String[] validArchiveKeywords = { ARCHIVE_LATEST, ARCHIVE_PREVIEW, ARCHIVE_VERSIONED }; for (Archive archive : archives) { if (Arrays.asList(validArchiveKeywords).contains(archive.id)) continue; // If the toolVersion is greater than or equal to the archive version we've found it @@ -98,7 +99,7 @@ private static String findLatestArchiveId(Archive[] archives, String toolVersion } } // Something wrong, go with the latest - return "latest"; + return ARCHIVE_LATEST; } /** @@ -111,20 +112,20 @@ private static String findLatestArchiveId(Archive[] archives, String toolVersion * Need to change array of policies into a string * ["CI162_5_2_DCP070116","CI162_5_2_DCP070116"] to "CI162_5_2_DCP070116,CI162_5_2_DCP070116" * - * @param ACConfig Provide the config object in which needs to be processed. + * @param acConfig Provide the config object in which needs to be processed. * * @return ConfigInternal - return the config object which has been made engine readable */ - private static ConfigInternal processACConfig(ConfigInternal ACConfig) throws IOException { - String[] validArchiveKeywords = { "latest", "preview", "versioned" }; - String ruleServer = ACConfig.ruleServer; + private static ConfigInternal processACConfig(ConfigInternal acConfig) throws IOException { + String[] validArchiveKeywords = { ARCHIVE_LATEST, ARCHIVE_PREVIEW, ARCHIVE_VERSIONED }; + String ruleServer = acConfig.ruleServer; // Get and parse the rule archive. String ruleArchiveFile = String.format("%s%s/archives.json",ruleServer,ruleServer.contains("jsdelivr.net")?"@next":""); Archive[] ruleArchiveParse; try { - ruleArchiveParse = Fetch.getJSONArr(ruleArchiveFile, Archive[].class, ACConfig.ignoreHTTPSErrors); + ruleArchiveParse = Fetch.getJSONArr(ruleArchiveFile, Archive[].class, acConfig.ignoreHTTPSErrors); } catch (Error err) { System.err.println(ruleArchiveFile); System.err.println(err.toString()); @@ -133,40 +134,39 @@ private static ConfigInternal processACConfig(ConfigInternal ACConfig) throws IO } String ruleArchivePath = null; if (ruleArchiveParse.length > 0) { - if (ACConfig.DEBUG) System.out.println("Found archiveFile: " + ruleArchiveFile); - ACConfig.ruleArchiveSet = ruleArchiveParse; - String ruleArchive = ACConfig.ruleArchive; + if (acConfig.DEBUG) System.out.println("Found archiveFile: " + ruleArchiveFile); + acConfig.ruleArchiveSet = ruleArchiveParse; + String ruleArchive = acConfig.ruleArchive; // If the user asked us to sync the rule version with the tool version, we need to figure out what the last rule version was - if ("versioned".equals(ruleArchive)) { - if (ACConfig.toolVersion == null) { - ruleArchive = "latest"; + if (ARCHIVE_VERSIONED.equals(ruleArchive)) { + if (acConfig.toolVersion == null) { + ruleArchive = ARCHIVE_LATEST; } else { - ruleArchive = findLatestArchiveId(ACConfig.ruleArchiveSet, ACConfig.toolVersion); + ruleArchive = findLatestArchiveId(acConfig.ruleArchiveSet, acConfig.toolVersion); } } - ACConfig.ruleArchiveLabel = ACConfig.ruleArchive; - for (int i = 0; i < ACConfig.ruleArchiveSet.length; i++) { - if (ruleArchive.equals(ACConfig.ruleArchiveSet[i].id) && !ACConfig.ruleArchiveSet[i].sunset) { - ruleArchivePath = ACConfig.ruleArchiveSet[i].path; - ACConfig.ruleArchiveVersion = ACConfig.ruleArchiveSet[i].version; - ACConfig.ruleArchiveLabel = ruleArchiveParse[i].name + " (" + ruleArchiveParse[i].id + ")"; + acConfig.ruleArchiveLabel = acConfig.ruleArchive; + for (int i = 0; i < acConfig.ruleArchiveSet.length; i++) { + if (ruleArchive.equals(acConfig.ruleArchiveSet[i].id) && !acConfig.ruleArchiveSet[i].sunset) { + ruleArchivePath = acConfig.ruleArchiveSet[i].path; + acConfig.ruleArchiveVersion = acConfig.ruleArchiveSet[i].version; + acConfig.ruleArchiveLabel = ruleArchiveParse[i].name + " (" + ruleArchiveParse[i].id + ")"; break; } } - if (ruleArchivePath == null || ACConfig.ruleArchiveVersion == null) { + if (ruleArchivePath == null || acConfig.ruleArchiveVersion == null) { String errStr = "[ERROR] RuleArchiveInvalid: Make Sure correct rule archive is provided in the configuration file. More information is available in the README.md"; System.err.println(errStr); throw new ConfigError(errStr); } - for (int i = 0; i < ACConfig.ruleArchiveSet.length; i++) { - if (ACConfig.ruleArchiveVersion.equals(ACConfig.ruleArchiveSet[i].version) - && !Arrays.asList(validArchiveKeywords).contains(ACConfig.ruleArchiveSet[i].id)) + for (int i = 0; i < acConfig.ruleArchiveSet.length; i++) { + if (acConfig.ruleArchiveVersion.equals(acConfig.ruleArchiveSet[i].version) + && !Arrays.asList(validArchiveKeywords).contains(acConfig.ruleArchiveSet[i].id)) { - ACConfig.ruleArchivePath = ACConfig.ruleArchiveSet[i].path; + acConfig.ruleArchivePath = acConfig.ruleArchiveSet[i].path; break; } } - //} } else { String errStr = "[ERROR] UnableToParseArchive: Archives are unable to be parse. Contact support team."; System.err.println(errStr); @@ -174,21 +174,21 @@ private static ConfigInternal processACConfig(ConfigInternal ACConfig) throws IO } // Build the new rulePack based of the baseA11yServerURL - if (ACConfig.rulePack == null || "".equals(ACConfig.rulePack)) { + if (acConfig.rulePack == null || "".equals(acConfig.rulePack)) { if (ruleServer.contains("jsdelivr.net")) { - ACConfig.rulePack = String.format("%s@%s", ruleServer, ACConfig.ruleArchiveVersion); + acConfig.rulePack = String.format("%s@%s", ruleServer, acConfig.ruleArchiveVersion); } else { - ACConfig.rulePack = String.format("%s%s/js", ruleServer, ruleArchivePath); + acConfig.rulePack = String.format("%s%s/js", ruleServer, ruleArchivePath); } } - ACConfig.ruleServer = ruleServer; + acConfig.ruleServer = ruleServer; - if (ACConfig.DEBUG) System.err.println("Built new rulePack: " + ACConfig.rulePack); + if (acConfig.DEBUG) System.err.println("Built new rulePack: " + acConfig.rulePack); - if (ACConfig.DEBUG) System.err.println("END 'processACConfig' function"); + if (acConfig.DEBUG) System.err.println("END 'processACConfig' function"); // Return the updated ACConfig object - return ACConfig; + return acConfig; } /** @@ -199,7 +199,7 @@ private static ConfigInternal processACConfig(ConfigInternal ACConfig) throws IO */ private static void initializeDefaults(ConfigInternal config) { // Use an unpopulated config as the default values - ConfigInternal ACConstants = new ConfigInternal(); + ConfigInternal acConstants = new ConfigInternal(); if (config.DEBUG) System.out.println("START 'initializeDefaults' function"); if (config.DEBUG) System.out.println("Config before initialization: "); @@ -208,7 +208,7 @@ private static void initializeDefaults(ConfigInternal config) { config.ruleArchiveLabel = Misc.firstNotNull(config.ruleArchiveLabel, config.ruleArchive); // For capture screenshots need to check for null or undefined and then set default otherwise it will evaluate the // boolean which causes it to always comply with the default value and not user provided option - config.captureScreenshots = Misc.firstNotNull(config.captureScreenshots, ACConstants.captureScreenshots); + config.captureScreenshots = Misc.firstNotNull(config.captureScreenshots, acConstants.captureScreenshots); // Build the toolID based on name and version config.toolID = "java-accessibility-checker-v3.1.70"; @@ -219,13 +219,13 @@ private static void initializeDefaults(ConfigInternal config) { // are done for a single run of karma. config.scanID = java.util.UUID.randomUUID().toString(); - for (Field field : ACConstants.getClass().getDeclaredFields()) { + for (Field field : acConstants.getClass().getDeclaredFields()) { try { if (field.get(config) == null) { - field.set(config, field.get(ACConstants)); + field.set(config, field.get(acConstants)); } - } catch (IllegalArgumentException e) { - } catch (IllegalAccessException e) { + } catch (IllegalArgumentException | IllegalAccessException e) { + // Skip if we can't access the field } } @@ -243,15 +243,15 @@ private static void initializeDefaults(ConfigInternal config) { */ private static ConfigInternal loadConfigFromJSONFile() { // Use an unpopulated config as the default values - ConfigInternal ACConstants = new ConfigInternal(); + ConfigInternal acConstants = new ConfigInternal(); - if (ACConstants.DEBUG) System.out.println("START 'loadConfigFromJSONFile' function"); + if (acConstants.DEBUG) System.out.println("START 'loadConfigFromJSONFile' function"); // Get the current working directory, where we will look for the yaml, yml or json file String workingDir = System.getProperty("user.dir"); - if (ACConstants.DEBUG) System.out.println("Working directory set to: " + workingDir); + if (acConstants.DEBUG) System.out.println("Working directory set to: " + workingDir); - String[] configFiles = ACConstants.configFiles; + String[] configFiles = acConstants.configFiles; ConfigInternal config = null; // Loop over all the possible location where the config file can reside, if one is found load it and break out. @@ -264,7 +264,7 @@ private static ConfigInternal loadConfigFromJSONFile() { // If this is a yml or yaml file verify that the file exists and then load as such. if ("json".equals(fileExtension)) { - if (ACConstants.DEBUG) System.out.println(fileToCheck+": Trying to load as json or js."); + if (acConstants.DEBUG) System.out.println(fileToCheck+": Trying to load as json or js."); // Need to use try/catch mech so that in the case the require throws an exception, we can // catch this and discatd the error, as in the case there is no config file provided then @@ -273,15 +273,15 @@ private static ConfigInternal loadConfigFromJSONFile() { Gson gson = new Gson(); JsonReader reader = new JsonReader(new FileReader(fileToCheck)); config = gson.fromJson(reader, ConfigInternal.class); - if (ACConstants.DEBUG) System.out.println(fileToCheck+": LOADED"); + if (acConstants.DEBUG) System.out.println(fileToCheck+": LOADED"); return config; } catch (FileNotFoundException e) { - if (ACConstants.DEBUG) System.out.println(fileToCheck+": Skipping, JSON file does not exist."); + if (acConstants.DEBUG) System.out.println(fileToCheck+": Skipping, JSON file does not exist."); } } } - if (ACConstants.DEBUG) System.out.println("END 'loadConfigFromJSONFile' function"); + if (acConstants.DEBUG) System.out.println("END 'loadConfigFromJSONFile' function"); return config; } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java index 555aa880f..c2161abcd 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java @@ -68,7 +68,7 @@ public Object clone() { return ret; } } - public static class Result extends ACEReport.Result implements Cloneable { + public static class Result extends ACEReport.Result { /** Did this issue match a baseline */ public boolean ignored = false; /** Help url for this item */ @@ -81,6 +81,7 @@ public Result(ACEReport.Result engineResult) { super(engineResult); } + @Override public Object clone() { return super.clone(); } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java index 412e8517a..85d08e118 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java @@ -15,12 +15,6 @@ *****************************************************************************/ package com.ibm.able.equalaccess.engine; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; import com.ibm.able.equalaccess.config.ConfigInternal; import com.ibm.able.equalaccess.report.CompressedReport; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java index 5e3582ed6..b7e2d7109 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java @@ -51,20 +51,20 @@ public void loadEngine() throws IOException { @Override public ACEReport getCompliance(String label) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getCompliance'"); + // Can't getCompliance with no content model + throw new UnsupportedOperationException("Cannot 'getCompliance' with EngineContextLocal"); } @Override public String getUrl() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getUrl'"); + // Can't getUrl with no content model + throw new UnsupportedOperationException("Cannot 'getUrl' with EngineContextLocal"); } @Override public String getTitle() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'getTitle'"); + // Can't getTitle with no content model + throw new UnsupportedOperationException("Cannot 'getTitle' with EngineContextLocal"); } @Override @@ -93,7 +93,17 @@ public String encodeURIComponent(String s) { engineScope = engine.initStandardObjects(); } String scriptStr = String.format("encodeURIComponent(`%s`)", s); - String result = engine.evaluateString(engineScope, scriptStr, "", 1, null).toString(); - return result; + return engine.evaluateString(engineScope, scriptStr, "", 1, null).toString(); + } + + @Override + public String getProfile() { + return "Local"; + } + + @Override + public String getHelp(String ruleId, String reasonId, String helpRoot) { + String scriptStr = String.format("ace_checker.engine.getHelp(`%s`,`%s`,`%s`)", ruleId, reasonId, helpRoot); + return engine.evaluateString(engineScope, scriptStr, "", 1, null).toString(); } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java index 8f949f314..795c0b34a 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java @@ -16,9 +16,9 @@ package com.ibm.able.equalaccess.enginecontext; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; -import org.openqa.selenium.WebDriver; - +import com.ibm.able.equalaccess.engine.ACError; import com.ibm.able.equalaccess.util.Misc; public class EngineContextManager { @@ -32,8 +32,29 @@ public static IEngineContext getEngineContext(Object contentContext) { IEngineContext engineContext = null; if (contentContext == null) { engineContext = new EngineContextLocal(); - } else if (Misc.classIsAvailable("org.openqa.selenium.WebDriver") && contentContext instanceof org.openqa.selenium.WebDriver) { - engineContext = new EngineContextSelenium((WebDriver) contentContext); + } + if (engineContext == null + && Misc.classIsAvailable("org.openqa.selenium.WebDriver")) + { + if (!Misc.classIsAvailable("com.ibm.able.equalaccess.enginecontext.selenium.EngineContextSelenium")) { + System.err.println("Attempted scan with WebDriver, but com.ibm.able.equalaccess.enginecontext.selenium.EngineContextSelenium could not be loaded"); + throw new ACError("Attempted scan with WebDriver, but com.ibm.able.equalaccess.enginecontext.selenium.EngineContextSelenium could not be loaded"); + } + try { + Class webdriverClass = Class.forName("org.openqa.selenium.WebDriver"); + if (webdriverClass.isAssignableFrom(contentContext.getClass())) { + // We have a webdriver, use EngineContextSelenium to instantiate it + Class ecClass = Class.forName("com.ibm.able.equalaccess.enginecontext.selenium.EngineContextSelenium"); + engineContext = (IEngineContext) ecClass.getConstructor(webdriverClass).newInstance(contentContext); + } + } catch (ClassNotFoundException e) { + } catch (NoSuchMethodException e) { + } catch (SecurityException e) { + } catch (InstantiationException e) { + } catch (IllegalAccessException e) { + } catch (IllegalArgumentException e) { + } catch (InvocationTargetException e) { + } } if (engineContext != null) { try { @@ -42,6 +63,9 @@ public static IEngineContext getEngineContext(Object contentContext) { System.err.println("aChecker: Unable to load engine due to IOException: "+e.toString()); e.printStackTrace(); } + } else { + System.err.println("Unable to load engine context for "+contentContext.getClass().getName()); + throw new ACError("Unable to load engine context for "+contentContext.getClass().getName()); } return engineContext; } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java index dac3d8e2a..3d5b00236 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java @@ -29,4 +29,11 @@ public interface IEngineContext { public String getTitle(); public Guideline[] getGuidelines(); public Rule[] getRules(); + public String getHelp(String ruleId, String reasonId, String helpRoot); + public String encodeURIComponent(String s); + /** + * The profile to use in metrics for this engine context + * @return profile string (e.g., Selenium) + */ + public String getProfile(); } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextSelenium.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java similarity index 92% rename from java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextSelenium.java rename to java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java index 608db3a46..10ceeb8db 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextSelenium.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ -package com.ibm.able.equalaccess.enginecontext; +package com.ibm.able.equalaccess.enginecontext.selenium; import java.io.IOException; import java.time.Duration; @@ -31,6 +31,7 @@ import com.ibm.able.equalaccess.engine.ACError; import com.ibm.able.equalaccess.engine.Guideline; import com.ibm.able.equalaccess.engine.Rule; +import com.ibm.able.equalaccess.enginecontext.IEngineContext; import com.ibm.able.equalaccess.engine.ACEReport; import com.ibm.able.equalaccess.util.Fetch; @@ -154,7 +155,6 @@ public ACEReport getCompliance(String label) { ACEReport report; try { this.driver.manage().timeouts().scriptTimeout(Duration.ofMinutes(60)); - this.driver.manage().timeouts().setScriptTimeout(Duration.ofMinutes(60)); String jsonReport = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr).toString(); if (!jsonReport.startsWith("{\"results\":[")) { throw new ACError(jsonReport); @@ -229,4 +229,21 @@ public Rule[] getRules() { String jsonGuidelines = ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr).toString(); return gson.fromJson(jsonGuidelines, Rule[].class); } + + @Override + public String getProfile() { + return "Selenium"; + } + + @Override + public String getHelp(String ruleId, String reasonId, String helpRoot) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getHelp'"); + } + + @Override + public String encodeURIComponent(String s) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'encodeURIComponent'"); + } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java index d5a664155..8ba8b1446 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java @@ -18,7 +18,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -62,7 +61,7 @@ public ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, scanTimesV2.get(profile).add(""+storedReport.engineReport.summary.scanTime); } return null; - }; + } @Override public ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, long endReport, @@ -88,7 +87,7 @@ public ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, // Dispatch the call to the metrics server try { - Fetch.get(this.metricsURLV2 + "/api/pub/meter/v2" + qs.toString()); + Fetch.get(this.metricsURLV2 + "/api/pub/meter/v2" + qs); } catch (Throwable t) { System.err.println(t); } @@ -100,8 +99,7 @@ public ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, // Dispatch the call to the metrics server try { - System.out.println(this.metricsURLV2 + "/api/pub/meter/v2" + qs.toString()); - Fetch.get(this.metricsURLV2 + "/api/pub/meter/v2" + qs.toString()); + Fetch.get(this.metricsURLV2 + "/api/pub/meter/v2" + qs); } catch (Throwable t) { System.err.println(t); } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/BaselineManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/BaselineManager.java index 0b2f7673f..0ea851961 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/BaselineManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/BaselineManager.java @@ -20,7 +20,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.stream.Stream; import com.google.gson.Gson; import com.ibm.able.equalaccess.abs.IAbstractAPI; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java index 683008c5a..fa8962176 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java @@ -27,6 +27,7 @@ import com.google.gson.Gson; import com.ibm.able.equalaccess.abs.IAbstractAPI; +import com.ibm.able.equalaccess.config.ACConfigManager; import com.ibm.able.equalaccess.config.ConfigInternal; import com.ibm.able.equalaccess.engine.ACEReport; import com.ibm.able.equalaccess.engine.ACError; @@ -35,6 +36,8 @@ import com.ibm.able.equalaccess.engine.eRuleConfidence; import com.ibm.able.equalaccess.engine.eRuleLevel; import com.ibm.able.equalaccess.engine.ACReport.Result; +import com.ibm.able.equalaccess.enginecontext.EngineContextManager; +import com.ibm.able.equalaccess.enginecontext.IEngineContext; public class ReporterManager { private static Gson gson = new Gson(); @@ -199,9 +202,11 @@ public static eRuleLevel valueToLevel(String[] reportValue) { return reportLevel; } + private static final IEngineContext engine = EngineContextManager.getEngineContext(null); private String getHelpUrl(ACReport.Result issue) { if (issue.help != null && issue.help.length() > 0) return issue.help; - return ""; + ConfigInternal config = ACConfigManager.getConfigUnsupported(); + String helpUrl = engine.getHelp(issue.ruleId, issue.reasonId, config.ruleArchivePath == null ? config.ruleArchive : config.ruleArchivePath.substring(config.ruleArchivePath.lastIndexOf("/")+1)); // TODO: // let config = ReporterManager.config; // let helpUrl = ReporterManager.absAPI.getChecker().engine.getHelp(issue.ruleId, issue.reasonId, !config.ruleArchivePath ? config.ruleArchive : config.ruleArchivePath.substring(config.ruleArchivePath.lastIndexOf("/")+1)); @@ -213,7 +218,7 @@ private String getHelpUrl(ACReport.Result issue) { // ruleId: issue.ruleId, // msgArgs: issue.messageArgs // }; - // return `${helpUrl}#${encodeURIComponent(JSON.stringify(minIssue))}` + return helpUrl+"#";//+encodeURIComponent(JSON.stringify(minIssue))}` } public void generateSummaries() { diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java index e882adb59..fe23e7b62 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java @@ -31,6 +31,7 @@ import java.util.Set; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.openqa.selenium.SessionNotCreatedException; import org.openqa.selenium.chrome.ChromeDriver; @@ -73,6 +74,11 @@ public static class UnitTestInfo { * Setup a Selenium Chrome environment before tests */ @BeforeClass public static void setup() { + // Make sure we're starting with a clean config + File configFile = new File("achecker.json"); + configFile.delete(); + ACConfigManager.resetConfig(); + String workingDir = System.getProperty("user.dir"); String chromeDriverDir = System.getenv("chromedriverpath"); ChromeOptions options = new ChromeOptions(); diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/config/ACConfigManagerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/config/ACConfigManagerTest.java index c22d8b7e2..f04a6b0d3 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/config/ACConfigManagerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/config/ACConfigManagerTest.java @@ -26,9 +26,17 @@ import java.nio.file.Paths; import java.util.regex.Pattern; +import org.junit.Before; import org.junit.Test; public class ACConfigManagerTest { + @Before public void setup() throws IOException { + // Make sure we're starting with a clean slate + File configFile = new File("achecker.json"); + configFile.delete(); + ACConfigManager.resetConfig(); + } + @Test public void getConfigWithNoConfigFile() { Config config = ACConfigManager.getConfig(); @@ -76,10 +84,10 @@ public class ACConfigManagerTest { } @Test public void getConfigWithConfigFile() throws IOException { - ACConfigManager.resetConfig(); File configFile = new File("achecker.json"); try { configFile.delete(); + ACConfigManager.resetConfig(); FileWriter myWriter = new FileWriter("achecker.json"); myWriter.write(""" { @@ -149,14 +157,15 @@ public class ACConfigManagerTest { assertEquals("DEFAULT", configInternal.engineMode); } finally { configFile.delete(); + ACConfigManager.resetConfig(); } } @Test public void getConfigWithConfigFileVersioned() throws IOException { - ACConfigManager.resetConfig(); File configFile = new File("achecker.json"); try { configFile.delete(); + ACConfigManager.resetConfig(); FileWriter myWriter = new FileWriter("achecker.json"); myWriter.write(""" { @@ -226,6 +235,7 @@ public class ACConfigManagerTest { assertEquals("DEFAULT", configInternal.engineMode); } finally { configFile.delete(); + ACConfigManager.resetConfig(); } } diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/util/FetchTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/util/FetchTest.java index c9882d5bf..6ce610e2d 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/util/FetchTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/util/FetchTest.java @@ -20,8 +20,6 @@ import java.io.IOException; -import com.ibm.able.equalaccess.util.Fetch; - public class FetchTest { @Test public void getArr() { String s = null; From 255c20940f6ad88864222e6a5f45ce8e23a72877 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Thu, 15 Aug 2024 12:01:11 -0500 Subject: [PATCH 044/161] CSV report / memory improvements --- .../able/equalaccess/abs/IAbstractAPI.java | 2 + .../com/ibm/able/equalaccess/abs/MyFS.java | 5 +- .../equalaccess/engine/ACReportSummary.java | 14 +-- .../equalaccess/report/ACReporterCSV.java | 90 +++++++++++++++++++ .../equalaccess/report/ACReporterJSON.java | 7 +- .../equalaccess/report/ACReporterMetrics.java | 3 +- .../equalaccess/report/CompressedReport.java | 30 +++++++ .../able/equalaccess/report/IReporter.java | 4 +- .../equalaccess/report/ReporterManager.java | 6 +- 9 files changed, 144 insertions(+), 17 deletions(-) create mode 100644 java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterCSV.java diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/IAbstractAPI.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/IAbstractAPI.java index 0808d5ea8..df2e47a6b 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/IAbstractAPI.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/IAbstractAPI.java @@ -15,11 +15,13 @@ *****************************************************************************/ package com.ibm.able.equalaccess.abs; +import java.io.File; import java.io.IOException; import com.ibm.able.equalaccess.engine.ACReport; public interface IAbstractAPI { public ACReport loadBaseline(String scanLabel); + public File prepFile(String filePath); public void writeFile(String path, Object contents) throws IOException; } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/MyFS.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/MyFS.java index a0237e697..956c41a7f 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/MyFS.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/abs/MyFS.java @@ -35,13 +35,14 @@ public class MyFS implements IAbstractAPI { @Override public void writeFile(String filePath, Object contents) throws IOException { - File outFile = this.prepFileSync(filePath); + File outFile = this.prepFile(filePath); FileWriter myWriter = new FileWriter(outFile); myWriter.write(contents.toString()); myWriter.close(); } - private File prepFileSync(String filePath) { + @Override + public File prepFile(String filePath) { ConfigInternal config = ACConfigManager.getConfigUnsupported(); Path outFile = Paths.get(System.getProperty("user.dir"), config.outputFolder, filePath); File f = outFile.toFile(); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java index 85d08e118..4fb1b57c9 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReportSummary.java @@ -16,6 +16,8 @@ package com.ibm.able.equalaccess.engine; +import java.util.List; + import com.ibm.able.equalaccess.config.ConfigInternal; import com.ibm.able.equalaccess.report.CompressedReport; import com.ibm.able.equalaccess.report.ReporterStored; @@ -50,8 +52,8 @@ public static class PageSummary { public PageSummary[] pageScanSummary = new PageSummary[0]; public ACReportSummary() {} - public ACReportSummary(ConfigInternal config, long endReport, CompressedReport[] compressedReports) { - this.startReport = compressedReports[0].getStartScan(); + public ACReportSummary(ConfigInternal config, long endReport, List compressedReports) { + this.startReport = compressedReports.get(0).getStartScan(); this.endReport = endReport; this.toolID = config.toolID; this.policies = config.policies; @@ -59,11 +61,11 @@ public ACReportSummary(ConfigInternal config, long endReport, CompressedReport[] this.labels = config.label; this.failLevels = config.failLevels; this.scanID = config.scanID; - this.pageScanSummary = new PageSummary[compressedReports.length]; - for (int idx=0; idx compressedReports) + { + long startScan = !compressedReports.isEmpty() ? compressedReports.get(0).getStartScan() : 0; + Date startScanD = new Date(startScan); + String reportFilename = "results_"+Misc.toISOString(startScanD).replace(":","-")+".csv"; + if (!config.outputFilenameTimestamp) { + reportFilename = "results.csv"; + } + + try { + FileWriter resultStr = new FileWriter(fsApi.prepFile(reportFilename)); + // StringBuilder resultStr = new StringBuilder(); + resultStr.append("Label,Level,RuleId,Message,Xpath,Help\n"); + for (CompressedReport compressedReport: compressedReports) { + for (int idx=0; idx compressedReports) { - if (compressedReports != null && compressedReports.length > 0) { + if (compressedReports != null && compressedReports.size() > 0) { ACReportSummary summReport = new ACReportSummary(config, endReport, compressedReports); if (summReport != null) { - Date startScan = new Date(compressedReports[0].getStartScan()); + Date startScan = new Date(compressedReports.get(0).getStartScan()); String reportFilename = "summary_"+Misc.toISOString(startScan).replaceAll(":","-")+".json"; if (!config.outputFilenameTimestamp) { reportFilename = "summary.json"; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java index 8ba8b1446..c86de32f4 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ACReporterMetrics.java @@ -17,6 +17,7 @@ import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.Map.Entry; @@ -65,7 +66,7 @@ public ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, @Override public ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, long endReport, - CompressedReport[] compressedReports) + List compressedReports) { try { // Variable Declaration diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java index b65fb0136..84e9fbe84 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java @@ -19,6 +19,7 @@ import java.util.Map; import com.ibm.able.equalaccess.engine.ACReport; +import com.ibm.able.equalaccess.engine.eRuleLevel; public class CompressedReport { public static String scanID; @@ -130,4 +131,33 @@ public long getStartScan() { public String getLabel() { return (String)data[3]; } + + public int issuesLength() { + return ((Object[][])data[10]).length; + } + + public eRuleLevel issueLevel(int idx) { + Object[] issue = ((Object[][])data[10])[idx]; + return ReporterManager.valueToLevel((String[])issue[2]); + } + + public String issueRuleId(int idx) { + Object[] issue = ((Object[][])data[10])[idx]; + return (String)issue[1]; + } + + public String issueMessage(int idx) { + Object[] issue = ((Object[][])data[10])[idx]; + return (String)issue[10]; + } + + public String issuePathDom(int idx) { + Object[] issue = ((Object[][])data[10])[idx]; + return ((Map)issue[5]).get("dom"); + } + + public String issueHelp(int idx) { + Object[] issue = ((Object[][])data[10])[idx]; + return (String)issue[8]; + } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/IReporter.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/IReporter.java index 95c5ed20a..9830bdac2 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/IReporter.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/IReporter.java @@ -15,6 +15,8 @@ *****************************************************************************/ package com.ibm.able.equalaccess.report; +import java.util.List; + import com.ibm.able.equalaccess.config.ConfigInternal; import com.ibm.able.equalaccess.engine.Guideline; @@ -24,5 +26,5 @@ public interface IReporter { * @return [ reportPath: string, report: string ] */ ReporterFile generateReport(ConfigInternal config, Guideline[] rulesets, ReporterStored reportData); - ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, long endReport, CompressedReport[] summaryData); + ReporterFile generateSummary(ConfigInternal config, Guideline[] rulesets, long endReport, List summaryData); }; \ No newline at end of file diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java index fa8962176..04c1f3a4a 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java @@ -74,8 +74,7 @@ private ReporterManager(ConfigInternal config, IAbstractAPI absAPI, Guideline[] // reporters.push(new ACReporterHTML()) } if (Arrays.asList(config.outputFormat).contains("csv")) { - // TODO: - // reporters.add(new ACReporterCSV()); + reporters.add(new ACReporterCSV(absAPI)); } if (Arrays.asList(config.outputFormat).contains("xlsx")) { // TODO: @@ -226,8 +225,7 @@ public void generateSummaries() { // If no scans, don't generate summaries if (reports.isEmpty()) return; for (IReporter reporter: reporters) { - CompressedReport[] cReports = reports.toArray(new CompressedReport[reports.size()]); - ReporterFile summaryInfo = reporter.generateSummary(config, rulesets, endReport, cReports); + ReporterFile summaryInfo = reporter.generateSummary(config, rulesets, endReport, reports); if (summaryInfo != null) { try { absAPI.writeFile(summaryInfo.path, summaryInfo.contents); From a3d937a44ffd54c21bf4b3b65d2ca6cb2b321b1e Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Thu, 15 Aug 2024 14:03:28 -0500 Subject: [PATCH 045/161] A minimal issue params to the help urls --- .../able/equalaccess/engine/ACEReport.java | 5 ++- .../ibm/able/equalaccess/engine/ACReport.java | 38 ++++++++++++++++++- .../enginecontext/EngineContextLocal.java | 2 +- .../equalaccess/report/ReporterManager.java | 13 +------ 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java index 77eddea40..0ed0f672d 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java @@ -17,6 +17,8 @@ package com.ibm.able.equalaccess.engine; import java.util.Map; +import com.google.gson.annotations.SerializedName; + public class ACEReport { public static class Result implements Cloneable { @@ -42,6 +44,7 @@ public Result(Result o) { /** Result message describing what was found */ public String message; /** Parameter parts used to construct the message */ + @SerializedName(value = "messageArgs", alternate = "msgArgs") public String[] messageArgs; /** Mapping of "dom", "aria", etc to identify the location of the result */ public Map path; @@ -68,7 +71,7 @@ public Object clone() { } ret.bounds = (Bounds) bounds.clone(); return ret; - } + } } public int numExecuted; diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java index c2161abcd..4486f28e2 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java @@ -15,6 +15,7 @@ *****************************************************************************/ package com.ibm.able.equalaccess.engine; +import java.lang.reflect.Type; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; @@ -23,6 +24,13 @@ import java.util.Set; import java.util.stream.Stream; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; import com.ibm.able.equalaccess.config.ConfigInternal; public class ACReport implements Cloneable { @@ -85,6 +93,34 @@ public Result(ACEReport.Result engineResult) { public Object clone() { return super.clone(); } + + public String toHelpData() { + return gsonMinimal.toJson(this); + } + + public static Gson gsonMinimal = new GsonBuilder() + .registerTypeAdapter(Result.class, new JsonSerializer() { + @Override + public JsonElement serialize(Result issue, Type typeOfSrc, JsonSerializationContext context) { + JsonObject jObject = new JsonObject(); + jObject.addProperty("ruleId", issue.ruleId); + jObject.addProperty("reasonId", issue.reasonId); + jObject.addProperty("message", issue.message); + jObject.addProperty("snippet", issue.snippet); + JsonArray buildValue = new JsonArray(); + for (String s: issue.value) { + buildValue.add(s); + } + jObject.add("value", buildValue); + JsonArray buildMsgArgs = new JsonArray(); + for (String s : issue.messageArgs) { + buildMsgArgs.add(s); + } + jObject.add("msgArgs", buildMsgArgs); + return jObject; + } + }) + .create(); } /** List of items detected by the getCompliance scan */ public Result[] results = new Result[0]; @@ -238,5 +274,5 @@ public Object clone() { ret.results[idx] = (ACReport.Result) results[idx].clone(); } return ret; - } + } } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java index b7e2d7109..918b81c5c 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java @@ -92,7 +92,7 @@ public String encodeURIComponent(String s) { // a scope object that we use in later calls. engineScope = engine.initStandardObjects(); } - String scriptStr = String.format("encodeURIComponent(`%s`)", s); + String scriptStr = String.format("encodeURIComponent(`%s`)", s.replace("\"", "\\\"")); return engine.evaluateString(engineScope, scriptStr, "", 1, null).toString(); } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java index 04c1f3a4a..f7000f4a6 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/ReporterManager.java @@ -206,18 +206,7 @@ private String getHelpUrl(ACReport.Result issue) { if (issue.help != null && issue.help.length() > 0) return issue.help; ConfigInternal config = ACConfigManager.getConfigUnsupported(); String helpUrl = engine.getHelp(issue.ruleId, issue.reasonId, config.ruleArchivePath == null ? config.ruleArchive : config.ruleArchivePath.substring(config.ruleArchivePath.lastIndexOf("/")+1)); - // TODO: - // let config = ReporterManager.config; - // let helpUrl = ReporterManager.absAPI.getChecker().engine.getHelp(issue.ruleId, issue.reasonId, !config.ruleArchivePath ? config.ruleArchive : config.ruleArchivePath.substring(config.ruleArchivePath.lastIndexOf("/")+1)); - // let minIssue = { - // message: issue.message, - // snippet: issue.snippet, - // value: issue.value, - // reasonId: issue.reasonId, - // ruleId: issue.ruleId, - // msgArgs: issue.messageArgs - // }; - return helpUrl+"#";//+encodeURIComponent(JSON.stringify(minIssue))}` + return helpUrl+"#"+engine.encodeURIComponent(issue.toHelpData()); } public void generateSummaries() { From 0eb83ff1b3e6648197194e781d4cedad7dde3d15 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 16 Aug 2024 09:30:18 -0500 Subject: [PATCH 046/161] Tighten dependencies, IOException --- java-accessibility-checker/lib/build.gradle | 21 +++++++----- .../enginecontext/EngineContextLocal.java | 34 +++++++++++-------- .../enginecontext/EngineContextManager.java | 7 +--- .../enginecontext/IEngineContext.java | 4 +-- .../selenium/EngineContextSelenium.java | 16 +++++---- 5 files changed, 45 insertions(+), 37 deletions(-) diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 44437ba39..0d9aac871 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -47,22 +47,27 @@ repositories { } dependencies { + implementation 'com.google.code.gson:gson:2.11.0' + // https://mavenlibs.com/maven/dependency/org.mozilla/rhino + implementation 'org.mozilla:rhino:1.7.14' + + // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java + seleniumImplementation 'org.seleniumhq.selenium:selenium-java:4.23.0' + seleniumImplementation 'com.google.code.gson:gson:2.11.0' + // https://mavenlibs.com/maven/dependency/org.mozilla/rhino + seleniumImplementation 'org.mozilla:rhino:1.7.14' + // Use JUnit test framework. testImplementation libs.junit + testImplementation 'org.seleniumhq.selenium:selenium-java:4.23.0' // This dependency is exported to consumers, that is to say found on their compile classpath. - api libs.commons.math3 + // api libs.commons.math3 // This dependency is used internally, and not exposed to consumers on their own compile classpath. - implementation libs.guava + // implementation libs.guava - implementation 'com.google.code.gson:gson:2.11.0' - // https://mavenlibs.com/maven/dependency/org.mozilla/rhino - implementation 'org.mozilla:rhino:1.7.14' - // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java - seleniumImplementation 'org.seleniumhq.selenium:selenium-java:4.23.0' - testImplementation 'org.seleniumhq.selenium:selenium-java:4.23.0' // implementation 'org.seleniumhq.selenium:selenium-java:4.23.0' } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java index 918b81c5c..7179552e0 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextLocal.java @@ -32,21 +32,27 @@ public class EngineContextLocal implements IEngineContext { private Scriptable engineScope = null; @Override - public void loadEngine() throws IOException { + public void loadEngine() { ConfigInternal config = ACConfigManager.getConfigUnsupported(); - String engineContent = Fetch.get(config.rulePack+"/ace.js", config.ignoreHTTPSErrors)+";var ace_checker = new ace.Checker();"; - - // Creates and enters a Context. The Context stores information - // about the execution environment of a script. - engine = Context.enter(); - - // Initialize the standard objects (Object, Function, etc.) - // This must be done before scripts can be executed. Returns - // a scope object that we use in later calls. - engineScope = engine.initStandardObjects(); - - // Now evaluate the string we've colected. - engine.evaluateString(engineScope, engineContent, "", 1, null); + String engineUrl = config.rulePack+"/ace.js"; + try { + String engineContent = Fetch.get(engineUrl, config.ignoreHTTPSErrors)+";var ace_checker = new ace.Checker();"; + + // Creates and enters a Context. The Context stores information + // about the execution environment of a script. + engine = Context.enter(); + + // Initialize the standard objects (Object, Function, etc.) + // This must be done before scripts can be executed. Returns + // a scope object that we use in later calls. + engineScope = engine.initStandardObjects(); + + // Now evaluate the string we've colected. + engine.evaluateString(engineScope, engineContent, "", 1, null); + } catch (IOException e) { + System.err.println("aChecker: Unable to load engine fromm "+engineUrl+" due to IOException: "+e.toString()); + e.printStackTrace(); + } } @Override diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java index 795c0b34a..6c157a6ee 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/EngineContextManager.java @@ -57,12 +57,7 @@ public static IEngineContext getEngineContext(Object contentContext) { } } if (engineContext != null) { - try { - engineContext.loadEngine(); - } catch (IOException e) { - System.err.println("aChecker: Unable to load engine due to IOException: "+e.toString()); - e.printStackTrace(); - } + engineContext.loadEngine(); } else { System.err.println("Unable to load engine context for "+contentContext.getClass().getName()); throw new ACError("Unable to load engine context for "+contentContext.getClass().getName()); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java index 3d5b00236..91e37586d 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/IEngineContext.java @@ -15,14 +15,12 @@ *****************************************************************************/ package com.ibm.able.equalaccess.enginecontext; -import java.io.IOException; - import com.ibm.able.equalaccess.engine.ACEReport; import com.ibm.able.equalaccess.engine.Guideline; import com.ibm.able.equalaccess.engine.Rule; public interface IEngineContext { - public void loadEngine() throws IOException; + public void loadEngine(); public ACEReport getCompliance(String label); public String getUrl(); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java index 10ceeb8db..b01c6bc1c 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java @@ -45,18 +45,19 @@ public EngineContextSelenium(WebDriver driver) { } @Override - public void loadEngine() throws IOException { + public void loadEngine() { ConfigInternal config = ACConfigManager.getConfigUnsupported(); + String engineUrl = config.rulePack+"/ace.js"; String engineLoadMode = config.engineMode; if ("DEFAULT".equals(engineLoadMode)) { engineLoadMode = "INJECT"; } - if ("INJECT".equals(engineLoadMode) && engineContent == null) { - engineContent = Fetch.get(config.rulePack+"/ace.js", config.ignoreHTTPSErrors); - } - - if (config.DEBUG) System.out.println("[INFO] aChecker.loadEngine detected Selenium"); try { + if ("INJECT".equals(engineLoadMode) && engineContent == null) { + engineContent = Fetch.get(engineUrl, config.ignoreHTTPSErrors); + } + + if (config.DEBUG) System.out.println("[INFO] aChecker.loadEngine detected Selenium"); String scriptStr; if ("REMOTE".equals(engineLoadMode)) { scriptStr = String.format(""" @@ -125,6 +126,9 @@ public void loadEngine() throws IOException { ((JavascriptExecutor)this.driver).executeAsyncScript(scriptStr); } catch (Error e) { System.err.println(e); + } catch (IOException e) { + System.err.println("aChecker: Unable to load engine from "+engineUrl+" due to IOException: "+e.toString()); + e.printStackTrace(); } } From a6624cf8ad5c35123ef4ec07d210bb1353eae9d7 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 16 Aug 2024 11:02:12 -0500 Subject: [PATCH 047/161] Tweak dependencies to not include selenium --- .../junit-selenium/lib/build.gradle | 14 ++---------- .../src/test/java/com/foo/SomeClassTest.java | 2 +- java-accessibility-checker/lib/build.gradle | 22 ++++++------------- 3 files changed, 10 insertions(+), 28 deletions(-) diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle index 1a6a4d2fb..538ac5366 100644 --- a/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/build.gradle @@ -28,20 +28,10 @@ dependencies { // Use JUnit test framework. testImplementation libs.junit - // This dependency is exported to consumers, that is to say found on their compile classpath. - api libs.commons.math3 - - // This dependency is used internally, and not exposed to consumers on their own compile classpath. - implementation libs.guava - // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java implementation 'org.seleniumhq.selenium:selenium-java:4.23.0' - implementation 'com.ibm.able.equalaccess:accessibility-checker:1.0.0-beta-3' - implementation('com.ibm.able.equalaccess:accessibility-checker:1.0.0-beta-3') { - capabilities { - requireCapability("com.ibm.able.equalaccess:selenium") - } - }} + implementation 'com.ibm.able.equalaccess:accessibility-checker:1.0.0-beta-5:selenium' +} // Apply a specific Java toolchain to ease working on different environments. java { diff --git a/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java index c04b93aca..e3b86591d 100644 --- a/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java +++ b/java-accessibility-checker/boilerplates/junit-selenium/lib/src/test/java/com/foo/SomeClassTest.java @@ -68,6 +68,6 @@ public class SomeClassTest { ACReport report = AccessibilityChecker.getCompliance(driver, "getComplianceTest"); eAssertResult resultCode = AccessibilityChecker.assertCompliance(report); - assertEquals(eAssertResult.PASS, resultCode); + assertEquals("Scan resulted in "+resultCode.toString(), eAssertResult.PASS, resultCode); } } diff --git a/java-accessibility-checker/lib/build.gradle b/java-accessibility-checker/lib/build.gradle index 0d9aac871..88702f448 100644 --- a/java-accessibility-checker/lib/build.gradle +++ b/java-accessibility-checker/lib/build.gradle @@ -13,7 +13,7 @@ plugins { } group 'com.ibm.able.equalaccess' -version '1.0.0-beta-3' +version '1.0.0-beta-5' archivesBaseName = 'accessibility-checker' sourceSets { @@ -50,9 +50,10 @@ dependencies { implementation 'com.google.code.gson:gson:2.11.0' // https://mavenlibs.com/maven/dependency/org.mozilla/rhino implementation 'org.mozilla:rhino:1.7.14' + seleniumCompileOnly 'org.seleniumhq.selenium:selenium-java:4.23.0' // https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java - seleniumImplementation 'org.seleniumhq.selenium:selenium-java:4.23.0' + // seleniumImplementation 'org.seleniumhq.selenium:selenium-java:4.23.0' seleniumImplementation 'com.google.code.gson:gson:2.11.0' // https://mavenlibs.com/maven/dependency/org.mozilla/rhino seleniumImplementation 'org.mozilla:rhino:1.7.14' @@ -60,15 +61,6 @@ dependencies { // Use JUnit test framework. testImplementation libs.junit testImplementation 'org.seleniumhq.selenium:selenium-java:4.23.0' - - // This dependency is exported to consumers, that is to say found on their compile classpath. - // api libs.commons.math3 - - // This dependency is used internally, and not exposed to consumers on their own compile classpath. - // implementation libs.guava - - - // implementation 'org.seleniumhq.selenium:selenium-java:4.23.0' } // Apply a specific Java toolchain to ease working on different environments. @@ -90,11 +82,11 @@ jar { // attributes "Main-Class": "com.baeldung.fatjar.Application" // } - from { - configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } - } + // from { + // configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + // } - duplicatesStrategy = DuplicatesStrategy.INCLUDE + // duplicatesStrategy = DuplicatesStrategy.INCLUDE } publishing { From 6f9615da0f425a114e614a5ea57b2e11d3ca8603 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 20 Aug 2024 13:52:21 -0500 Subject: [PATCH 048/161] Do all of the 'pass' processing in the page context --- .../src/ts/background/backgroundController.ts | 87 ++++++++++++------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/accessibility-checker-extension/src/ts/background/backgroundController.ts b/accessibility-checker-extension/src/ts/background/backgroundController.ts index f1b0acfb4..fde450956 100644 --- a/accessibility-checker-extension/src/ts/background/backgroundController.ts +++ b/accessibility-checker-extension/src/ts/background/backgroundController.ts @@ -15,7 +15,7 @@ *****************************************************************************/ import { getDevtoolsController } from "../devtools/devtoolsController"; -import { IArchiveDefinition, IIssue, IMessage, IReport, IRuleset, ISessionState, ISettings } from "../interfaces/interfaces"; +import { IArchiveDefinition, IIssue, IMessage, IReport, IRuleset, ISessionState, ISettings, IssueValue } from "../interfaces/interfaces"; import { CommonMessaging } from "../messaging/commonMessaging"; import { Controller, eControllerType, ListenerType } from "../messaging/controller"; import Config from "../util/config"; @@ -394,6 +394,63 @@ class BackgroundController extends Controller { } delete result.node; } + + // Process report before returning it to avoid large message passing of pass messages + if (report) { + let valueMap: { [key: string]: { [key2: string]: string } } = { + "VIOLATION": { + "POTENTIAL": "Needs review", + "FAIL": "Violation", + "PASS": "Pass", + "MANUAL": "Needs review" + }, + "RECOMMENDATION": { + "POTENTIAL": "Recommendation", + "FAIL": "Recommendation", + "PASS": "Pass", + "MANUAL": "Recommendation" + }, + "INFORMATION": { + "POTENTIAL": "Needs review", + "FAIL": "Violation", + "PASS": "Pass", + "MANUAL": "Recommendation" + } + }; + + let valueToStringSingular = (value: IssueValue) => { + return valueMap[value[0]][value[1]]; + } + for (const result of report.results) { + if (result.ruleTime > 50) { + console.info(`[PERF: ${result.ruleId}] ${result.ruleTime}`); + } + } + // let passResults = []; + let remainResults = []; + let counts = { + "Violation": 0, + "Needs review": 0, + "Recommendation": 0, + "Pass": 0, + total: 0 + }; + let xpaths : string[] = report.results.map((result) => result.path.dom); + report.testedUniqueElements = Array.from(new Set(xpaths)).length; + for (const result of report.results) { + let sing = valueToStringSingular(result.value); + ++counts[sing as eLevel]; + ++counts.total; + if (result.value[1] === "PASS" && result.value[0] !== "INFORMATION") { + // passResults.push(result); + } else { + remainResults.push(result); + } + } + report.results = remainResults; + report.counts = counts; + } + return report; } catch (err) { console.error(err); @@ -418,11 +475,6 @@ class BackgroundController extends Controller { this.metrics.sendLogsV2(); getDevtoolsController(toolTabId, false, "remote").setScanningState("processing"); if (report) { - for (const result of report.results) { - if (result.ruleTime > 50) { - console.info(`[PERF: ${result.ruleId}] ${result.ruleTime}`); - } - } report.results.sort((resultA, resultB) => { let valueA = UtilIssue.valueToStringSingular(resultA.value); let valueB = UtilIssue.valueToStringSingular(resultB.value); @@ -435,29 +487,6 @@ class BackgroundController extends Controller { if (valueB === "Recommendation") return 1; return 0; }); - // let passResults = []; - let remainResults = []; - let counts = { - "Violation": 0, - "Needs review": 0, - "Recommendation": 0, - "Pass": 0, - total: 0 - }; - let xpaths : string[] = report.results.map((result) => result.path.dom); - report.testedUniqueElements = Array.from(new Set(xpaths)).length; - for (const result of report.results) { - let sing = UtilIssue.valueToStringSingular(result.value); - ++counts[sing as eLevel]; - ++counts.total; - if (result.value[1] === "PASS" && result.value[0] !== "INFORMATION") { - // passResults.push(result); - } else { - remainResults.push(result); - } - } - report.results = remainResults; - report.counts = counts; } getDevtoolsController(toolTabId, false, "remote").setReport(report); From 31d83edd7d1ff096ff4c9496f59480aec3fbf0e4 Mon Sep 17 00:00:00 2001 From: Shunguo Date: Thu, 22 Aug 2024 10:01:40 -0500 Subject: [PATCH 049/161] add test cases and update rule logic --- .../v4/rules/aria_accessiblename_exists.ts | 4 +- .../src/v4/rules/aria_img_labelled.ts | 4 +- .../v4/rules/element_orientation_unlocked.ts | 4 +- .../src/v4/rules/img_alt_valid.ts | 2 +- .../src/v4/util/CSSUtil.ts | 8 ++-- .../act-fail4.html | 42 +++++++++++++++++++ 6 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-fail4.html diff --git a/accessibility-checker-engine/src/v4/rules/aria_accessiblename_exists.ts b/accessibility-checker-engine/src/v4/rules/aria_accessiblename_exists.ts index 5675d8356..97c9dc7c2 100644 --- a/accessibility-checker-engine/src/v4/rules/aria_accessiblename_exists.ts +++ b/accessibility-checker-engine/src/v4/rules/aria_accessiblename_exists.ts @@ -20,7 +20,7 @@ import { getDeprecatedAriaRoles, getDeprecatedAriaAttributes, getRolesUndefinedB export const aria_accessiblename_exists: Rule = { id: "aria_accessiblename_exists", - context: "aria:columnheader, aria:form, aria:heading, aria:rowheader, aria:table, aria:graphics-document,aria:graphics-symbol, aria:img, doc-backlink, doc-biblioentry, doc-biblioref, doc-glossref, doc-noteref, doc-pagebreak", + context: "aria:columnheader, aria:form, aria:heading, aria:rowheader, aria:table, aria:graphics-document,aria:graphics-symbol, doc-backlink, doc-biblioentry, doc-biblioref, doc-glossref, doc-noteref, doc-pagebreak", help: { "en-US": { "pass": "aria_accessiblename_exists.html", @@ -51,8 +51,6 @@ export const aria_accessiblename_exists: Rule = { let nodeName = ruleContext.nodeName.toLocaleLowerCase(); // svg element is handled in svg_graphics)labbelled rule if (nodeName === 'svg') return; - // img element handled in img_alt_valid - if (nodeName === "img" && ruleContext.hasAttribute("alt")) return RulePass("pass"); // when table element with a caption as first child if (nodeName === 'table' diff --git a/accessibility-checker-engine/src/v4/rules/aria_img_labelled.ts b/accessibility-checker-engine/src/v4/rules/aria_img_labelled.ts index a7f892c4a..4f0e76550 100644 --- a/accessibility-checker-engine/src/v4/rules/aria_img_labelled.ts +++ b/accessibility-checker-engine/src/v4/rules/aria_img_labelled.ts @@ -11,14 +11,14 @@ limitations under the License. *****************************************************************************/ -import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule"; +import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy } from "../api/IRule"; import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { RPTUtil } from "../../v2/checker/accessibility/util/legacy"; import { VisUtil } from "../../v2/dom/VisUtil"; export let aria_img_labelled: Rule = { id: "aria_img_labelled", - context: "aria:img", + context: "aria:img, aria:image", refactor: { "HAAC_Aria_ImgAlt": { "Pass_0": "Pass_0", diff --git a/accessibility-checker-engine/src/v4/rules/element_orientation_unlocked.ts b/accessibility-checker-engine/src/v4/rules/element_orientation_unlocked.ts index 502b4dae2..a913a5414 100644 --- a/accessibility-checker-engine/src/v4/rules/element_orientation_unlocked.ts +++ b/accessibility-checker-engine/src/v4/rules/element_orientation_unlocked.ts @@ -63,7 +63,7 @@ export let element_orientation_unlocked: Rule = { orientationTransforms = getMediaOrientationTransform(doc); setCache(doc, "RPTUtil_MEDIA_ORIENTATION_TRANSFROM", orientationTransforms); } - + console.log("node="+nodeName +", orientationTransforms="+JSON.stringify(orientationTransforms)); // find if the element matches orientation selector(s) let media_transforms = []; Object.keys(orientationTransforms).forEach(key => { @@ -72,7 +72,7 @@ export let element_orientation_unlocked: Rule = { media_transforms.push(orientationTransforms[key][tag].transform); }); }); - + console.log("node="+nodeName +", media_transforms="+JSON.stringify(media_transforms)); // no match, the element is not in media orientation transform if (media_transforms.length === 0) return null; diff --git a/accessibility-checker-engine/src/v4/rules/img_alt_valid.ts b/accessibility-checker-engine/src/v4/rules/img_alt_valid.ts index 259d0d7dc..ee76507a9 100644 --- a/accessibility-checker-engine/src/v4/rules/img_alt_valid.ts +++ b/accessibility-checker-engine/src/v4/rules/img_alt_valid.ts @@ -11,7 +11,7 @@ limitations under the License. *****************************************************************************/ -import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule"; +import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy } from "../api/IRule"; import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { RPTUtil } from "../../v2/checker/accessibility/util/legacy"; import { VisUtil } from "../../v2/dom/VisUtil"; diff --git a/accessibility-checker-engine/src/v4/util/CSSUtil.ts b/accessibility-checker-engine/src/v4/util/CSSUtil.ts index 8116fc42f..5fd21b3a6 100644 --- a/accessibility-checker-engine/src/v4/util/CSSUtil.ts +++ b/accessibility-checker-engine/src/v4/util/CSSUtil.ts @@ -193,18 +193,18 @@ export function getDefinedStyles(elem: HTMLElement, pseudoClass?: string ) { */ export function getMediaOrientationTransform(doc: Document) { let orientationTransforms = {} - + console.log("stylesheet="+JSON.stringify(doc.styleSheets)); // Iterate through all of the stylesheets and rules for (let ssIndex = 0; ssIndex < doc.styleSheets.length; ++ssIndex) { - const sheet = doc.styleSheets[ssIndex] as CSSStyleSheet; + const sheet = doc.styleSheets[ssIndex] as CSSStyleSheet; try { if (sheet && sheet.cssRules) { for (let rIndex = 0; rIndex < sheet.cssRules.length; ++rIndex) { - const sheetRule = sheet.cssRules[rIndex]; + const sheetRule = sheet.cssRules[rIndex]; if (4 /* CSSRule.MEDIA_RULE */ === sheetRule.MEDIA_RULE) { const rule = sheetRule as CSSMediaRule; if (rule && rule.media) { - const mediaList = rule.media; + const mediaList = rule.media; for (let i = 0; i < mediaList.length; i++) { let elem_transforms = orientationTransforms[mediaList.item(i).toLocaleLowerCase()]; if (!elem_transforms) elem_transforms = {}; diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-fail4.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-fail4.html new file mode 100644 index 000000000..2638caa8a --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-fail4.html @@ -0,0 +1,42 @@ + + + Page with some content + + + + Page Content + + + \ No newline at end of file From 0dced3c2ff481f23c57786fedf6fe094996e5223 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 23 Aug 2024 15:23:37 -0500 Subject: [PATCH 050/161] Do counting and "pass" filtering in the checking context --- accessibility-checker/src-ts/lib/ACHelper.ts | 287 +++++++++++++++++- common/module/src/engine/IReport.ts | 32 +- common/module/src/report/ReporterManager.ts | 20 +- .../src/lib/ACCommands.js | 70 +++++ .../src/lib/ACHelper.js | 72 ++++- 5 files changed, 447 insertions(+), 34 deletions(-) diff --git a/accessibility-checker/src-ts/lib/ACHelper.ts b/accessibility-checker/src-ts/lib/ACHelper.ts index ab1cd9ce3..5f50011df 100644 --- a/accessibility-checker/src-ts/lib/ACHelper.ts +++ b/accessibility-checker/src-ts/lib/ACHelper.ts @@ -229,6 +229,70 @@ async function getComplianceHelperSelenium(label, parsed, curPol) : Promise { + let reportLevel; + if (reportValue[1] === "PASS") { + reportLevel = "pass"; + } + else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") { + reportLevel = "manual"; + } + else if (reportValue[0] === "VIOLATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "violation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialviolation"; + } + } + else if (reportValue[0] === "RECOMMENDATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "recommendation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialrecommendation"; + } + } + return reportLevel; +} + +const getCounts = (engineReport) => { + let counts = { + violation: 0, + potentialviolation: 0, + recommendation: 0, + potentialrecommendation: 0, + manual: 0, + pass: 0, + ignored: 0, + elements: 0, + elementsViolation: 0, + elementsViolationReview: 0 + } + let elementSet = new Set(); + let elementViolationSet = new Set(); + let elementViolationReviewSet = new Set(); + for (const issue of engineReport.results) { + elementSet.add(issue.path.dom); + if (issue.ignored) { + ++counts.ignored; + } else { + ++counts[issue.level]; + if (issue.level === "violation") { + elementViolationSet.add(issue.path.dom); + elementViolationReviewSet.add(issue.path.dom); + } else if (issue.level === "potentialviolation" || issue.level === "manual") { + elementViolationReviewSet.add(issue.path.dom); + } + } + } + counts.elements = elementSet.size; + counts.elementsViolation = elementViolationSet.size; + counts.elementsViolationReview = elementViolationReviewSet.size + return counts; +} + let policies = ${JSON.stringify(Config.policies)}; let checker = new window.ace_ibma.Checker(); @@ -238,7 +302,14 @@ setTimeout(function() { checker.check(document, policies).then(function(report) { for (const result of report.results) { delete result.node; + result.level = valueToLevel(result.value) } + report.summary ||= {}; + report.summary.counts ||= getCounts(report); + let reportLevels = ${JSON.stringify((Config.reportLevels || []).concat(Config.failLevels || []).map(lvl => lvl.toString()))}; + // Filter out pass results unless they asked for them in reports + // We don't want to mess with baseline functions, but pass results can break the response object + report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass"); cb(report); }) },0) @@ -291,8 +362,71 @@ async function getComplianceHelperWebDriverIO(label, parsed, curPol) : Promise { + let report : IEngineReport = await page.executeAsync(({ policies, customRulesets, reportLevels }, done) => { + const valueToLevel = (reportValue) => { + let reportLevel; + if (reportValue[1] === "PASS") { + reportLevel = "pass"; + } + else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") { + reportLevel = "manual"; + } + else if (reportValue[0] === "VIOLATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "violation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialviolation"; + } + } + else if (reportValue[0] === "RECOMMENDATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "recommendation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialrecommendation"; + } + } + return reportLevel; + } + + const getCounts = (engineReport) => { + let counts = { + violation: 0, + potentialviolation: 0, + recommendation: 0, + potentialrecommendation: 0, + manual: 0, + pass: 0, + ignored: 0, + elements: 0, + elementsViolation: 0, + elementsViolationReview: 0 + } + let elementSet = new Set(); + let elementViolationSet = new Set(); + let elementViolationReviewSet = new Set(); + for (const issue of engineReport.results) { + elementSet.add(issue.path.dom); + if (issue.ignored) { + ++counts.ignored; + } else { + ++counts[issue.level]; + if (issue.level === "violation") { + elementViolationSet.add(issue.path.dom); + elementViolationReviewSet.add(issue.path.dom); + } else if (issue.level === "potentialviolation" || issue.level === "manual") { + elementViolationReviewSet.add(issue.path.dom); + } + } + } + counts.elements = elementSet.size; + counts.elementsViolation = elementViolationSet.size; + counts.elementsViolationReview = elementViolationReviewSet.size + return counts; + } + let checker = new (window as any).ace_ibma.Checker(); customRulesets.forEach((rs) => checker.addRuleset(rs)); return new Promise((resolve, reject) => { @@ -300,13 +434,19 @@ async function getComplianceHelperWebDriverIO(label, parsed, curPol) : Promise reportLevels.includes(result.level) || result.level !== "pass"); resolve(report); done(report); }) }, 0) }) - }, { policies: Config.policies, customRulesets: ACEngineManager.customRulesets }); + }, { policies: Config.policies, customRulesets: ACEngineManager.customRulesets, reportLevels: (Config.reportLevels || []).concat(Config.failLevels || []).map(lvl => lvl.toString()) }); if (curPol != null && !checkPolicy) { const valPolicies = ACEngineManager.customRulesets.map(rs => rs.id).concat(await page.execute(() => (new (window as any).ace_ibma.Checker().rulesetIds))); checkPolicy = true; @@ -347,8 +487,69 @@ async function getComplianceHelperPuppeteer(label, parsed, curPol) : Promise { - + let report : IEngineReport = await page.evaluate(({ policies, customRulesets, reportLevels }) => { + const valueToLevel = (reportValue) => { + let reportLevel; + if (reportValue[1] === "PASS") { + reportLevel = "pass"; + } + else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") { + reportLevel = "manual"; + } + else if (reportValue[0] === "VIOLATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "violation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialviolation"; + } + } + else if (reportValue[0] === "RECOMMENDATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "recommendation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialrecommendation"; + } + } + return reportLevel; + } + + const getCounts = (engineReport) => { + let counts = { + violation: 0, + potentialviolation: 0, + recommendation: 0, + potentialrecommendation: 0, + manual: 0, + pass: 0, + ignored: 0, + elements: 0, + elementsViolation: 0, + elementsViolationReview: 0 + } + let elementSet = new Set(); + let elementViolationSet = new Set(); + let elementViolationReviewSet = new Set(); + for (const issue of engineReport.results) { + elementSet.add(issue.path.dom); + if (issue.ignored) { + ++counts.ignored; + } else { + ++counts[issue.level]; + if (issue.level === "violation") { + elementViolationSet.add(issue.path.dom); + elementViolationReviewSet.add(issue.path.dom); + } else if (issue.level === "potentialviolation" || issue.level === "manual") { + elementViolationReviewSet.add(issue.path.dom); + } + } + } + counts.elements = elementSet.size; + counts.elementsViolation = elementViolationSet.size; + counts.elementsViolationReview = elementViolationReviewSet.size + return counts; + } let checker = new (window as any).ace_ibma.Checker(); customRulesets.forEach((rs) => checker.addRuleset(rs)); return new Promise((resolve, reject) => { @@ -356,12 +557,18 @@ async function getComplianceHelperPuppeteer(label, parsed, curPol) : Promise reportLevels.includes(result.level) || result.level !== "pass"); resolve(report); }) }, 0) }) - }, { policies: Config.policies, customRulesets: ACEngineManager.customRulesets }); + }, { policies: Config.policies, customRulesets: ACEngineManager.customRulesets, reportLevels: (Config.reportLevels || []).concat(Config.failLevels || []).map(lvl => lvl.toString()) }); if (curPol != null && !checkPolicy) { const valPolicies = ACEngineManager.customRulesets.map(rs => rs.id).concat(await page.evaluate("new window.ace_ibma.Checker().rulesetIds")); checkPolicy = true; @@ -399,6 +606,69 @@ async function getComplianceHelperPuppeteer(label, parsed, curPol) : Promise { try { + const valueToLevel = (reportValue) => { + let reportLevel; + if (reportValue[1] === "PASS") { + reportLevel = "pass"; + } + else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") { + reportLevel = "manual"; + } + else if (reportValue[0] === "VIOLATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "violation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialviolation"; + } + } + else if (reportValue[0] === "RECOMMENDATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "recommendation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialrecommendation"; + } + } + return reportLevel; + } + + const getCounts = (engineReport) => { + let counts = { + violation: 0, + potentialviolation: 0, + recommendation: 0, + potentialrecommendation: 0, + manual: 0, + pass: 0, + ignored: 0, + elements: 0, + elementsViolation: 0, + elementsViolationReview: 0 + } + let elementSet = new Set(); + let elementViolationSet = new Set(); + let elementViolationReviewSet = new Set(); + for (const issue of engineReport.results) { + elementSet.add(issue.path.dom); + if (issue.ignored) { + ++counts.ignored; + } else { + ++counts[issue.level]; + if (issue.level === "violation") { + elementViolationSet.add(issue.path.dom); + elementViolationReviewSet.add(issue.path.dom); + } else if (issue.level === "potentialviolation" || issue.level === "manual") { + elementViolationReviewSet.add(issue.path.dom); + } + } + } + counts.elements = elementSet.size; + counts.elementsViolation = elementViolationSet.size; + counts.elementsViolationReview = elementViolationReviewSet.size + return counts; + } + let startScan = Date.now(); let checker = ACEngineManager.getChecker(); ACEngineManager.customRulesets.forEach((rs) => checker.addGuideline(rs)); @@ -406,7 +676,14 @@ async function getComplianceHelperLocal(label, parsed, curPol) : Promise lvl.toString()); + // Filter out pass results unless they asked for them in reports + // We don't want to mess with baseline functions, but pass results can break the response object + report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass"); return report; }) diff --git a/common/module/src/engine/IReport.ts b/common/module/src/engine/IReport.ts index 5c42187e4..1da743258 100644 --- a/common/module/src/engine/IReport.ts +++ b/common/module/src/engine/IReport.ts @@ -65,6 +65,9 @@ export type IEngineReport = { [ruleId: string]: { [reasonId: string]: string } + }, + summary?: { + counts?: SummaryCounts } } @@ -76,6 +79,19 @@ export type IBaselineResult = IEngineResult & { level: eRuleLevel } +export type SummaryCounts = { + violation: number, + potentialviolation: number, + recommendation: number, + potentialrecommendation: number, + manual: number, + pass: number, + ignored: number, + elements: number, + elementsViolation: number, + elementsViolationReview: number +} + export type IBaselineReport = { results: IBaselineResult[] numExecuted: number, @@ -85,18 +101,7 @@ export type IBaselineReport = { } } summary: { - counts: { - violation: number, - potentialviolation: number, - recommendation: number, - potentialrecommendation: number, - manual: number, - pass: number, - ignored: number, - elements: number, - elementsViolation: number, - elementsViolationReview: number - } + counts: SummaryCounts, scanTime: number, ruleArchive: string policies: string[] @@ -120,7 +125,8 @@ export type CompressedReport = [ string, // ruleArchive string[], // policies string[], // reportLevels - CompressedIssue[] + CompressedIssue[], + SummaryCounts ] export type CompressedIssue = [ // results diff --git a/common/module/src/report/ReporterManager.ts b/common/module/src/report/ReporterManager.ts index 605fc8a5c..b1524b1b0 100644 --- a/common/module/src/report/ReporterManager.ts +++ b/common/module/src/report/ReporterManager.ts @@ -105,7 +105,8 @@ export class ReporterManager { report.engineReport.summary.ruleArchive, // 7 report.engineReport.summary.policies, // 8 report.engineReport.summary.reportLevels, // 9 - compressedResults // 10 + compressedResults, // 10 + report.engineReport.summary.counts // 11 ] for (let idx=0; idx 32000) { @@ -151,18 +152,7 @@ export class ReporterManager { numExecuted: report[5], nls, summary: { - counts: { - violation: 0, - potentialviolation: 0, - recommendation: 0, - potentialrecommendation: 0, - manual: 0, - pass: 0, - ignored: 0, - elements: 0, - elementsViolation: 0, - elementsViolationReview: 0 - }, + counts: report[11], scanTime: report[6], ruleArchive: report[7], policies: report[8], @@ -174,7 +164,6 @@ export class ReporterManager { toolID: ReporterManager.toolID, label: report[3] } - engineReport.summary.counts = ReporterManager.getCounts(engineReport); return { startScan: report[0], url: report[1], @@ -390,7 +379,7 @@ export class ReporterManager { }); (retVal as any).summary = {}; - retVal.summary.counts = ReporterManager.getCounts(retVal); + retVal.summary.counts = engineResult.summary.counts || ReporterManager.getCounts(engineResult as any); retVal.results = retVal.results.filter(pageResult => { if (ReporterManager.config.reportLevels.includes(pageResult.level)) { @@ -460,6 +449,7 @@ export class ReporterManager { counts.elements = elementSet.size; counts.elementsViolation = elementViolationSet.size; counts.elementsViolationReview = elementViolationReviewSet.size + console.log(counts.pass); return counts; } diff --git a/cypress-accessibility-checker/src/lib/ACCommands.js b/cypress-accessibility-checker/src/lib/ACCommands.js index 87a573493..6248aa080 100644 --- a/cypress-accessibility-checker/src/lib/ACCommands.js +++ b/cypress-accessibility-checker/src/lib/ACCommands.js @@ -16,6 +16,69 @@ let logger = { create: loggerCreate }; +function valueToLevel(reportValue) { + let reportLevel; + if (reportValue[1] === "PASS") { + reportLevel = "pass"; + } + else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") { + reportLevel = "manual"; + } + else if (reportValue[0] === "VIOLATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "violation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialviolation"; + } + } + else if (reportValue[0] === "RECOMMENDATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "recommendation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialrecommendation"; + } + } + return reportLevel; +} + +function getCounts(engineReport) { + let counts = { + violation: 0, + potentialviolation: 0, + recommendation: 0, + potentialrecommendation: 0, + manual: 0, + pass: 0, + ignored: 0, + elements: 0, + elementsViolation: 0, + elementsViolationReview: 0 + } + let elementSet = new Set(); + let elementViolationSet = new Set(); + let elementViolationReviewSet = new Set(); + for (const issue of engineReport.results) { + elementSet.add(issue.path.dom); + if (issue.ignored) { + ++counts.ignored; + } else { + ++counts[issue.level]; + if (issue.level === "violation") { + elementViolationSet.add(issue.path.dom); + elementViolationReviewSet.add(issue.path.dom); + } else if (issue.level === "potentialviolation" || issue.level === "manual") { + elementViolationReviewSet.add(issue.path.dom); + } + } + } + counts.elements = elementSet.size; + counts.elementsViolation = elementViolationSet.size; + counts.elementsViolationReview = elementViolationReviewSet.size + return counts; +} + let ACCommands = module.exports = { DEBUG: false, initialize: (win, fileConfig) => { @@ -107,7 +170,14 @@ let ACCommands = module.exports = { .then(function (report) { for (const result of report.results) { delete result.node; + result.level = valueToLevel(result.value) } + report.summary ||= {}; + report.summary.counts ||= getCounts(report); + let reportLevels = (ACCommands.Config.reportLevels || []).concat(ACCommands.Config.failLevels || []); + // Filter out pass results unless they asked for them in reports + // We don't want to mess with baseline functions, but pass results can break the response object + report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass"); return report; }) } catch (err) { diff --git a/karma-accessibility-checker/src/lib/ACHelper.js b/karma-accessibility-checker/src/lib/ACHelper.js index 20f5cda98..53ba04001 100644 --- a/karma-accessibility-checker/src/lib/ACHelper.js +++ b/karma-accessibility-checker/src/lib/ACHelper.js @@ -235,7 +235,70 @@ let aChecker = { * @memberOf this */ aChecker.runScan = async function (content, policies, url, pageTitle, label, iframeWindow) { - try { + try { + const valueToLevel = (reportValue) => { + let reportLevel; + if (reportValue[1] === "PASS") { + reportLevel = "pass"; + } + else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") { + reportLevel = "manual"; + } + else if (reportValue[0] === "VIOLATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "violation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialviolation"; + } + } + else if (reportValue[0] === "RECOMMENDATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "recommendation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialrecommendation"; + } + } + return reportLevel; + } + + const getCounts = (engineReport) => { + let counts = { + violation: 0, + potentialviolation: 0, + recommendation: 0, + potentialrecommendation: 0, + manual: 0, + pass: 0, + ignored: 0, + elements: 0, + elementsViolation: 0, + elementsViolationReview: 0 + } + let elementSet = new Set(); + let elementViolationSet = new Set(); + let elementViolationReviewSet = new Set(); + for (const issue of engineReport.results) { + elementSet.add(issue.path.dom); + if (issue.ignored) { + ++counts.ignored; + } else { + ++counts[issue.level]; + if (issue.level === "violation") { + elementViolationSet.add(issue.path.dom); + elementViolationReviewSet.add(issue.path.dom); + } else if (issue.level === "potentialviolation" || issue.level === "manual") { + elementViolationReviewSet.add(issue.path.dom); + } + } + } + counts.elements = elementSet.size; + counts.elementsViolation = elementViolationSet.size; + counts.elementsViolationReview = elementViolationReviewSet.size + return counts; + } + // Get the Data when the scan is started // Start time will be in milliseconds elapsed since 1 January 1970 00:00:00 UTC up until now. const startScan = Date.now(); @@ -247,7 +310,14 @@ let aChecker = { let engineReport = await checker.check(content, policies); for (const result of engineReport.results) { delete result.node; + result.level = valueToLevel(result.value) } + let reportLevels = (aChecker.Config.reportLevels || []).concat(aChecker.Config.failLevels || []).map(lvl => lvl.toString()); + report.summary ||= {}; + report.summary.counts ||= getCounts(report); + // Filter out pass results unless they asked for them in reports + // We don't want to mess with baseline functions, but pass results can break the response object + report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass"); ReporterManager.config = BaselineManager.config = aChecker.Config; From 3f496e4fa8c8a13bb1d18cefa9d7a134ba56d06a Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 23 Aug 2024 16:03:10 -0500 Subject: [PATCH 051/161] typescript --- accessibility-checker-engine/src/v4/api/IRule.ts | 3 ++- common/module/src/engine/IRule.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/accessibility-checker-engine/src/v4/api/IRule.ts b/accessibility-checker-engine/src/v4/api/IRule.ts index 19c1bdae8..32a0fd6f3 100644 --- a/accessibility-checker-engine/src/v4/api/IRule.ts +++ b/accessibility-checker-engine/src/v4/api/IRule.ts @@ -101,7 +101,8 @@ export type Issue = RuleResult & { ruleTime: number, message: string, bounds?: Bounds, - snippet: string + snippet: string, + level?: string } export type RuleContextHierarchy = { [namespace: string] : IMapResult[] }; diff --git a/common/module/src/engine/IRule.ts b/common/module/src/engine/IRule.ts index f10a64d8c..dd65ba100 100644 --- a/common/module/src/engine/IRule.ts +++ b/common/module/src/engine/IRule.ts @@ -99,7 +99,8 @@ export type Issue = RuleResult & { ruleTime: number, message: string, bounds?: Bounds, - snippet: string + snippet: string, + level?: string } export type RuleContextHierarchy = { [namespace: string] : IMapResult[] }; From 31fea343225ecdfac2b2285a7f51dbc004ec088b Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 23 Aug 2024 16:10:53 -0500 Subject: [PATCH 052/161] Wrong variable --- karma-accessibility-checker/src/lib/ACHelper.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/karma-accessibility-checker/src/lib/ACHelper.js b/karma-accessibility-checker/src/lib/ACHelper.js index 53ba04001..719b8e616 100644 --- a/karma-accessibility-checker/src/lib/ACHelper.js +++ b/karma-accessibility-checker/src/lib/ACHelper.js @@ -313,11 +313,11 @@ let aChecker = { result.level = valueToLevel(result.value) } let reportLevels = (aChecker.Config.reportLevels || []).concat(aChecker.Config.failLevels || []).map(lvl => lvl.toString()); - report.summary ||= {}; - report.summary.counts ||= getCounts(report); + engineReport.summary ||= {}; + engineReport.summary.counts ||= getCounts(engineReport); // Filter out pass results unless they asked for them in reports // We don't want to mess with baseline functions, but pass results can break the response object - report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass"); + engineReport.results = engineReport.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass"); ReporterManager.config = BaselineManager.config = aChecker.Config; From b2670d47df10a6dcb6536590c4c6095c9cd8efe6 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 23 Aug 2024 16:52:24 -0500 Subject: [PATCH 053/161] Fix counting --- accessibility-checker/src-ts/lib/ACHelper.ts | 102 ++---------------- common/module/src/report/ReporterManager.ts | 16 +-- .../src/lib/ACCommands.js | 24 +---- .../src/lib/ACHelper.js | 26 +---- .../src/lib/ReporterManager.js | 15 +-- 5 files changed, 24 insertions(+), 159 deletions(-) diff --git a/accessibility-checker/src-ts/lib/ACHelper.ts b/accessibility-checker/src-ts/lib/ACHelper.ts index 5f50011df..9213a1be9 100644 --- a/accessibility-checker/src-ts/lib/ACHelper.ts +++ b/accessibility-checker/src-ts/lib/ACHelper.ts @@ -264,35 +264,15 @@ const getCounts = (engineReport) => { recommendation: 0, potentialrecommendation: 0, manual: 0, - pass: 0, - ignored: 0, - elements: 0, - elementsViolation: 0, - elementsViolationReview: 0 + pass: 0 } - let elementSet = new Set(); - let elementViolationSet = new Set(); - let elementViolationReviewSet = new Set(); for (const issue of engineReport.results) { - elementSet.add(issue.path.dom); - if (issue.ignored) { - ++counts.ignored; - } else { - ++counts[issue.level]; - if (issue.level === "violation") { - elementViolationSet.add(issue.path.dom); - elementViolationReviewSet.add(issue.path.dom); - } else if (issue.level === "potentialviolation" || issue.level === "manual") { - elementViolationReviewSet.add(issue.path.dom); - } - } + ++counts[issue.level]; } - counts.elements = elementSet.size; - counts.elementsViolation = elementViolationSet.size; - counts.elementsViolationReview = elementViolationReviewSet.size return counts; } + let policies = ${JSON.stringify(Config.policies)}; let checker = new window.ace_ibma.Checker(); @@ -398,32 +378,11 @@ async function getComplianceHelperWebDriverIO(label, parsed, curPol) : Promise checker.addRuleset(rs)); return new Promise((resolve, reject) => { @@ -640,32 +579,11 @@ async function getComplianceHelperLocal(label, parsed, curPol) : Promise { if (ReporterManager.config.reportLevels.includes(pageResult.level)) { @@ -416,18 +416,13 @@ export class ReporterManager { return retVal; } - private static getCounts(engineReport: IBaselineReport) { + private static addCounts(engineReport: IBaselineReport) { let counts = { - violation: 0, - potentialviolation: 0, - recommendation: 0, - potentialrecommendation: 0, - manual: 0, - pass: 0, ignored: 0, elements: 0, elementsViolation: 0, - elementsViolationReview: 0 + elementsViolationReview: 0, + ...engineReport.summary.counts } let elementSet = new Set(); let elementViolationSet = new Set(); @@ -436,8 +431,8 @@ export class ReporterManager { elementSet.add(issue.path.dom); if (issue.ignored) { ++counts.ignored; + --counts[issue.level.toString()]; } else { - ++counts[issue.level.toString()]; if (issue.level === eRuleLevel.violation) { elementViolationSet.add(issue.path.dom); elementViolationReviewSet.add(issue.path.dom); @@ -449,7 +444,6 @@ export class ReporterManager { counts.elements = elementSet.size; counts.elementsViolation = elementViolationSet.size; counts.elementsViolationReview = elementViolationReviewSet.size - console.log(counts.pass); return counts; } diff --git a/cypress-accessibility-checker/src/lib/ACCommands.js b/cypress-accessibility-checker/src/lib/ACCommands.js index 6248aa080..f1d715121 100644 --- a/cypress-accessibility-checker/src/lib/ACCommands.js +++ b/cypress-accessibility-checker/src/lib/ACCommands.js @@ -49,33 +49,11 @@ function getCounts(engineReport) { potentialviolation: 0, recommendation: 0, potentialrecommendation: 0, - manual: 0, - pass: 0, - ignored: 0, - elements: 0, - elementsViolation: 0, - elementsViolationReview: 0 + manual: 0 } - let elementSet = new Set(); - let elementViolationSet = new Set(); - let elementViolationReviewSet = new Set(); for (const issue of engineReport.results) { elementSet.add(issue.path.dom); - if (issue.ignored) { - ++counts.ignored; - } else { - ++counts[issue.level]; - if (issue.level === "violation") { - elementViolationSet.add(issue.path.dom); - elementViolationReviewSet.add(issue.path.dom); - } else if (issue.level === "potentialviolation" || issue.level === "manual") { - elementViolationReviewSet.add(issue.path.dom); - } - } } - counts.elements = elementSet.size; - counts.elementsViolation = elementViolationSet.size; - counts.elementsViolationReview = elementViolationReviewSet.size return counts; } diff --git a/karma-accessibility-checker/src/lib/ACHelper.js b/karma-accessibility-checker/src/lib/ACHelper.js index 719b8e616..b49117054 100644 --- a/karma-accessibility-checker/src/lib/ACHelper.js +++ b/karma-accessibility-checker/src/lib/ACHelper.js @@ -270,35 +270,15 @@ let aChecker = { recommendation: 0, potentialrecommendation: 0, manual: 0, - pass: 0, - ignored: 0, - elements: 0, - elementsViolation: 0, - elementsViolationReview: 0 + pass: 0 } - let elementSet = new Set(); - let elementViolationSet = new Set(); - let elementViolationReviewSet = new Set(); for (const issue of engineReport.results) { - elementSet.add(issue.path.dom); - if (issue.ignored) { - ++counts.ignored; - } else { - ++counts[issue.level]; - if (issue.level === "violation") { - elementViolationSet.add(issue.path.dom); - elementViolationReviewSet.add(issue.path.dom); - } else if (issue.level === "potentialviolation" || issue.level === "manual") { - elementViolationReviewSet.add(issue.path.dom); - } - } + ++counts[issue.level]; } - counts.elements = elementSet.size; - counts.elementsViolation = elementViolationSet.size; - counts.elementsViolationReview = elementViolationReviewSet.size return counts; } + // Get the Data when the scan is started // Start time will be in milliseconds elapsed since 1 January 1970 00:00:00 UTC up until now. const startScan = Date.now(); diff --git a/karma-accessibility-checker/src/lib/ReporterManager.js b/karma-accessibility-checker/src/lib/ReporterManager.js index ce00870e2..ac55612be 100644 --- a/karma-accessibility-checker/src/lib/ReporterManager.js +++ b/karma-accessibility-checker/src/lib/ReporterManager.js @@ -142,7 +142,7 @@ class ReporterManager { }); retVal.summary = {}; - retVal.summary.counts = ReporterManager.getCounts(retVal); + retVal.summary.counts = ReporterManager.addCounts(retVal); retVal.results = retVal.results.filter(pageResult => { if (ReporterManager.config.reportLevels.includes(pageResult.level)) { @@ -179,18 +179,13 @@ class ReporterManager { return retVal; } - static getCounts(engineReport) { + static addCounts(engineReport) { let counts = { - violation: 0, - potentialviolation: 0, - recommendation: 0, - potentialrecommendation: 0, - manual: 0, - pass: 0, ignored: 0, elements: 0, elementsViolation: 0, - elementsViolationReview: 0 + elementsViolationReview: 0, + ...engineReport.summary.counts } let elementSet = new Set(); let elementViolationSet = new Set(); @@ -199,8 +194,8 @@ class ReporterManager { elementSet.add(issue.path.dom); if (issue.ignored) { ++counts.ignored; + --counts[issue.level.toString()]; } else { - ++counts[issue.level.toString()]; if (issue.level === eRuleLevel.violation) { elementViolationSet.add(issue.path.dom); elementViolationReviewSet.add(issue.path.dom); From 6de1516723fe4b3721f863d32d59a12956d57f6e Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 23 Aug 2024 17:03:10 -0500 Subject: [PATCH 054/161] Typescript bug --- accessibility-checker/src-ts/lib/ACHelper.ts | 8 ++++---- common/module/src/engine/IReport.ts | 11 ++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/accessibility-checker/src-ts/lib/ACHelper.ts b/accessibility-checker/src-ts/lib/ACHelper.ts index 9213a1be9..6f68a2f0c 100644 --- a/accessibility-checker/src-ts/lib/ACHelper.ts +++ b/accessibility-checker/src-ts/lib/ACHelper.ts @@ -6,7 +6,7 @@ import { IConfigInternal } from "./common/config/IConfig"; import { ReporterManager } from "./common/report/ReporterManager"; import { existsSync, mkdirSync, writeFileSync } from "fs"; import { IAbstractAPI } from "./common/api-ext/IAbstractAPI"; -import { IBaselineReport, IEngineReport } from "./common/engine/IReport"; +import { EngineSummaryCounts, IBaselineReport, IEngineReport } from "./common/engine/IReport"; import { dirname, join, resolve as pathResolve } from "path"; import { BaselineManager, RefactorMap } from "./common/report/BaselineManager"; @@ -372,7 +372,7 @@ async function getComplianceHelperWebDriverIO(label, parsed, curPol) : Promise { - let counts = { + let counts: EngineSummaryCounts = { violation: 0, potentialviolation: 0, recommendation: 0, @@ -475,7 +475,7 @@ async function getComplianceHelperPuppeteer(label, parsed, curPol) : Promise { - let counts = { + let counts: EngineSummaryCounts = { violation: 0, potentialviolation: 0, recommendation: 0, @@ -573,7 +573,7 @@ async function getComplianceHelperLocal(label, parsed, curPol) : Promise { - let counts = { + let counts: EngineSummaryCounts = { violation: 0, potentialviolation: 0, recommendation: 0, diff --git a/common/module/src/engine/IReport.ts b/common/module/src/engine/IReport.ts index 1da743258..b36abbbc3 100644 --- a/common/module/src/engine/IReport.ts +++ b/common/module/src/engine/IReport.ts @@ -67,7 +67,7 @@ export type IEngineReport = { } }, summary?: { - counts?: SummaryCounts + counts?: EngineSummaryCounts } } @@ -79,6 +79,15 @@ export type IBaselineResult = IEngineResult & { level: eRuleLevel } +export type EngineSummaryCounts = { + violation: number, + potentialviolation: number, + recommendation: number, + potentialrecommendation: number, + manual: number, + pass: number +} + export type SummaryCounts = { violation: number, potentialviolation: number, From a957835a74d1290f2e12ab5eaf537d7d1966eec2 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 23 Aug 2024 19:33:41 -0500 Subject: [PATCH 055/161] init counts --- common/module/src/report/ReporterManager.ts | 6 ++++-- karma-accessibility-checker/src/lib/ReporterManager.js | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/common/module/src/report/ReporterManager.ts b/common/module/src/report/ReporterManager.ts index d2da3aa29..d914e27f9 100644 --- a/common/module/src/report/ReporterManager.ts +++ b/common/module/src/report/ReporterManager.ts @@ -378,8 +378,10 @@ export class ReporterManager { } }); - (retVal as any).summary = {}; - retVal.summary.counts = ReporterManager.addCounts(engineResult as any); + (retVal as any).summary = { + counts: engineResult.summary.counts + }; + retVal.summary.counts = ReporterManager.addCounts(retVal); retVal.results = retVal.results.filter(pageResult => { if (ReporterManager.config.reportLevels.includes(pageResult.level)) { diff --git a/karma-accessibility-checker/src/lib/ReporterManager.js b/karma-accessibility-checker/src/lib/ReporterManager.js index ac55612be..14daa7235 100644 --- a/karma-accessibility-checker/src/lib/ReporterManager.js +++ b/karma-accessibility-checker/src/lib/ReporterManager.js @@ -141,7 +141,9 @@ class ReporterManager { } }); - retVal.summary = {}; + retVal.summary = { + counts: retVal.summary.counts + }; retVal.summary.counts = ReporterManager.addCounts(retVal); retVal.results = retVal.results.filter(pageResult => { From 19f9112fe032652a4f7a0fa95a145096e2d0e2d4 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 23 Aug 2024 19:38:21 -0500 Subject: [PATCH 056/161] fix count --- cypress-accessibility-checker/src/lib/ACCommands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress-accessibility-checker/src/lib/ACCommands.js b/cypress-accessibility-checker/src/lib/ACCommands.js index f1d715121..ced1ae95c 100644 --- a/cypress-accessibility-checker/src/lib/ACCommands.js +++ b/cypress-accessibility-checker/src/lib/ACCommands.js @@ -52,7 +52,7 @@ function getCounts(engineReport) { manual: 0 } for (const issue of engineReport.results) { - elementSet.add(issue.path.dom); + ++counts[issue.level]; } return counts; } From a01115592efd84f60b25969b70eb0a3e446bd375 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Fri, 23 Aug 2024 23:14:49 -0500 Subject: [PATCH 057/161] Handle large result --- .../karmaaction.conf.js | 2 +- .../able/equalaccess/engine/ACEReport.java | 33 +++++++++++ .../ibm/able/equalaccess/engine/ACReport.java | 49 ++++++++++++---- .../selenium/EngineContextSelenium.java | 56 ++++++++++++++++++- .../equalaccess/report/CompressedReport.java | 5 +- .../equalaccess/report/ReporterManager.java | 2 +- .../equalaccess/AccessibilityCheckerTest.java | 6 +- 7 files changed, 136 insertions(+), 17 deletions(-) diff --git a/accessibility-checker-engine/karmaaction.conf.js b/accessibility-checker-engine/karmaaction.conf.js index ff4a434ad..f56a824fe 100644 --- a/accessibility-checker-engine/karmaaction.conf.js +++ b/accessibility-checker-engine/karmaaction.conf.js @@ -63,7 +63,7 @@ module.exports = (config) => { customLaunchers: { ChromeCustom: { base: 'ChromeHeadless', - flags: ['--disable-web-security', '--no-sandbox'] + flags: ['--disable-gpu', '--disable-web-security', '--no-sandbox'] } }, preprocessors: { diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java index 0ed0f672d..3441196e3 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACEReport.java @@ -20,6 +20,38 @@ import com.google.gson.annotations.SerializedName; public class ACEReport { + public static class SummaryCounts implements Cloneable { + public int violation = 0; + public int potentialviolation = 0; + public int recommendation = 0; + public int potentialrecommendation = 0; + public int manual = 0; + public int pass = 0; + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException ex) { + System.err.println(ex); + throw new RuntimeException(); + } + } + } + public static class Summary implements Cloneable { + public SummaryCounts counts = new SummaryCounts(); + + public Object clone() { + Summary ret = null; + try { + ret = (Summary) super.clone(); + } catch (CloneNotSupportedException ex) { + System.err.println(ex); + throw new RuntimeException(); + } + ret.counts = (SummaryCounts)counts.clone(); + return ret; + } + } public static class Result implements Cloneable { public Result() {} @@ -80,4 +112,5 @@ public Object clone() { public Map> nls; public Result[] results; public String screenshot=null; + public Summary summary; } diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java index 4486f28e2..b0da859fb 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/engine/ACReport.java @@ -54,6 +54,18 @@ public Object clone() { throw new RuntimeException(); } } + + public SummaryCounts() { + } + + public SummaryCounts(ACEReport.SummaryCounts rhs) { + violation = rhs.violation; + potentialviolation = rhs.potentialviolation; + recommendation = rhs.recommendation; + potentialrecommendation = rhs.potentialrecommendation; + manual = rhs.manual; + pass = rhs.pass; + } } public static class Summary implements Cloneable { public SummaryCounts counts = new SummaryCounts(); @@ -167,6 +179,25 @@ public void updateSummaryCounts() { counts.potentialrecommendation = 0; counts.manual = 0; counts.pass = 0; + for (Result issue: results) { + if (eRuleLevel.violation.equals(issue.level)) { + ++counts.violation; + } else if (eRuleLevel.potentialviolation.equals(issue.level)) { + ++counts.potentialviolation; + } else if (eRuleLevel.recommendation.equals(issue.level)) { + ++counts.recommendation; + } else if (eRuleLevel.potentialrecommendation.equals(issue.level)) { + ++counts.potentialrecommendation; + } else if (eRuleLevel.manual.equals(issue.level)) { + ++counts.manual; + } else if (eRuleLevel.pass.equals(issue.level)) { + ++counts.pass; + } + } + } + + public void addCounts(ACEReport.SummaryCounts summaryCounts) { + SummaryCounts counts = this.summary.counts = new SummaryCounts(summaryCounts); counts.ignored = 0; counts.elements = 0; counts.elementsViolation = 0; @@ -178,22 +209,20 @@ public void updateSummaryCounts() { elementSet.add(issue.path.get("dom")); if (issue.ignored) { ++counts.ignored; - } else { if (eRuleLevel.violation.equals(issue.level)) { - ++counts.violation; + --counts.violation; } else if (eRuleLevel.potentialviolation.equals(issue.level)) { - ++counts.potentialviolation; + --counts.potentialviolation; } else if (eRuleLevel.recommendation.equals(issue.level)) { - ++counts.recommendation; + --counts.recommendation; } else if (eRuleLevel.potentialrecommendation.equals(issue.level)) { - ++counts.potentialrecommendation; + --counts.potentialrecommendation; } else if (eRuleLevel.manual.equals(issue.level)) { - ++counts.manual; + --counts.manual; } else if (eRuleLevel.pass.equals(issue.level)) { - ++counts.pass; - } else if (eRuleLevel.ignored.equals(issue.level)) { - ++counts.ignored; - } + --counts.pass; + } + } else { if (eRuleLevel.violation.equals(issue.level)) { elementViolationSet.add(issue.path.get("dom")); elementViolationReviewSet.add(issue.path.get("dom")); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java index b01c6bc1c..02c9705a8 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/enginecontext/selenium/EngineContextSelenium.java @@ -17,6 +17,9 @@ import java.io.IOException; import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.OutputType; @@ -136,10 +139,54 @@ public void loadEngine() { public ACEReport getCompliance(String label) { Config config = ACConfigManager.getConfig(); try { + List resultList = new ArrayList<>(config.reportLevels.length + config.failLevels.length); + Collections.addAll(resultList, config.reportLevels); + Collections.addAll(resultList, config.failLevels); String scriptStr = String.format(""" let cb = arguments[arguments.length - 1]; try { + const valueToLevel = (reportValue) => { + let reportLevel; + if (reportValue[1] === "PASS") { + reportLevel = "pass"; + } + else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") { + reportLevel = "manual"; + } + else if (reportValue[0] === "VIOLATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "violation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialviolation"; + } + } + else if (reportValue[0] === "RECOMMENDATION") { + if (reportValue[1] === "FAIL") { + reportLevel = "recommendation"; + } + else if (reportValue[1] === "POTENTIAL") { + reportLevel = "potentialrecommendation"; + } + } + return reportLevel; + } + const getCounts = (engineReport) => { + let counts = { + violation: 0, + potentialviolation: 0, + recommendation: 0, + potentialrecommendation: 0, + manual: 0, + pass: 0 + } + for (const issue of engineReport.results) { + ++counts[issue.level]; + } + return counts; + } let policies = %s; + let reportLevels = %s; let checker = new window.ace_ibma.Checker(); let customRulesets = []; @@ -148,14 +195,19 @@ public ACEReport getCompliance(String label) { checker.check(document, policies).then(function(report) { for (const result of report.results) { delete result.node; + result.level = valueToLevel(result.value) } - cb(JSON.stringify(report)); + report.summary ||= {}; + report.summary.counts ||= getCounts(report); + // Filter out pass results unless they asked for them in reports + // We don't want to mess with baseline functions, but pass results can break the response object + report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass"); cb(JSON.stringify(report)); }) },0) } catch (e) { cb(e); } - """, gson.toJson(config.policies) /* TODO: ${JSON.stringify(ACEngineManager.customRulesets)}; */); + """, gson.toJson(config.policies), gson.toJson(resultList.toArray()) /* TODO: ${JSON.stringify(ACEngineManager.customRulesets)}; */); ACEReport report; try { this.driver.manage().timeouts().scriptTimeout(Duration.ofMinutes(60)); diff --git a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java index 84e9fbe84..ad21645fc 100644 --- a/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java +++ b/java-accessibility-checker/lib/src/main/java/com/ibm/able/equalaccess/report/CompressedReport.java @@ -44,7 +44,8 @@ public CompressedReport(ReporterStored info) { summary.ruleArchive, // ruleArchive (7) summary.policies, // policies (8) summary.reportLevels, // reportLevels (9) - new Object[report.results.length][] // (10) + new Object[report.results.length][], // (10) + summary.counts }; for (int idx=0; idx Date: Fri, 23 Aug 2024 23:49:26 -0500 Subject: [PATCH 058/161] Debug --- .../com/ibm/able/equalaccess/AccessibilityCheckerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java index 67ac5554c..8337e2b8e 100644 --- a/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java +++ b/java-accessibility-checker/lib/src/test/java/com/ibm/able/equalaccess/AccessibilityCheckerTest.java @@ -229,8 +229,8 @@ private void listFiles(File f, java.util.List retFiles) { } } } - assertEquals("Issue triggered was not expected", 0, actualIssues.size()); - assertEquals("Expected issue was not triggered ("+testFile.getAbsolutePath()+")\n---\n"+gson.toJson(report.results)+"\n---\n"+gson.toJson(expectedIssues), 0, expectedIssues.size()); + assertEquals(testFile.toString()+": Issue triggered was not expected", 0, actualIssues.size()); + assertEquals(testFile.toString()+": Expected issue was not triggered ("+testFile.getAbsolutePath()+")\n---\n"+gson.toJson(report.results)+"\n---\n"+gson.toJson(expectedIssues), 0, expectedIssues.size()); } } } From 4d480e57b6a69160c36b9ffb14c0b550f9dc74fa Mon Sep 17 00:00:00 2001 From: Shunguo Date: Sun, 25 Aug 2024 22:52:51 -0500 Subject: [PATCH 059/161] update the rule and the test case result #1958 --- .../src/v4/rules/aria_img_labelled.ts | 6 ++- .../v4/rules/element_orientation_unlocked.ts | 28 +++++++++---- .../src/v4/util/CSSUtil.ts | 4 +- .../aria_imge.html | 42 +++++++++++++++++++ .../act-fail1.html | 2 +- .../act-fail4.html | 18 ++++---- .../act-pass3.html | 40 ++++++++++++++++++ 7 files changed, 119 insertions(+), 21 deletions(-) create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_accessiblename_exists_ruleunit/aria_imge.html create mode 100644 accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-pass3.html diff --git a/accessibility-checker-engine/src/v4/rules/aria_img_labelled.ts b/accessibility-checker-engine/src/v4/rules/aria_img_labelled.ts index 4f0e76550..d23f98c2e 100644 --- a/accessibility-checker-engine/src/v4/rules/aria_img_labelled.ts +++ b/accessibility-checker-engine/src/v4/rules/aria_img_labelled.ts @@ -12,7 +12,6 @@ *****************************************************************************/ import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy } from "../api/IRule"; -import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { RPTUtil } from "../../v2/checker/accessibility/util/legacy"; import { VisUtil } from "../../v2/dom/VisUtil"; @@ -62,6 +61,11 @@ export let aria_img_labelled: Rule = { // If no role, this is implicit, and covered by WCAG20_Img_HasAlt return null; } + + let nodeName = ruleContext.nodeName.toLocaleLowerCase(); + // svg and img elements are handled in svg_graphics_labbelled and img_alt_valid rules + if (nodeName === 'svg' || nodeName === 'img') return; + /* removed the role check role= presentation since if an element has role=img, then there needs to be a check for alt attribute regardless of the presecne of role=presentation if (RPTUtil.hasRole(ruleContext, "presentation") || RPTUtil.hasRole(ruleContext, "none")){ return RulePass(1); diff --git a/accessibility-checker-engine/src/v4/rules/element_orientation_unlocked.ts b/accessibility-checker-engine/src/v4/rules/element_orientation_unlocked.ts index a913a5414..2fb395a26 100644 --- a/accessibility-checker-engine/src/v4/rules/element_orientation_unlocked.ts +++ b/accessibility-checker-engine/src/v4/rules/element_orientation_unlocked.ts @@ -19,7 +19,7 @@ import { getCache, setCache } from "../util/CacheUtil"; import { FragmentUtil } from "../../v2/checker/accessibility/util/fragment"; import { RPTUtil } from "../../v2/checker/accessibility/util/legacy"; -export let element_orientation_unlocked: Rule = { +export const element_orientation_unlocked: Rule = { id: "element_orientation_unlocked", context: "dom:*", help: { @@ -54,7 +54,7 @@ export let element_orientation_unlocked: Rule = { if (RPTUtil.getAncestor(ruleContext, ["script", "meta", "title"])) return null; - const nodeName = ruleContext.nodeName.toLowerCase(); + const nodeName = ruleContext.nodeName.toLowerCase(); // cache the orientation result for all the elements in the page let doc = FragmentUtil.getOwnerFragment(ruleContext) as any; @@ -63,22 +63,30 @@ export let element_orientation_unlocked: Rule = { orientationTransforms = getMediaOrientationTransform(doc); setCache(doc, "RPTUtil_MEDIA_ORIENTATION_TRANSFROM", orientationTransforms); } - console.log("node="+nodeName +", orientationTransforms="+JSON.stringify(orientationTransforms)); + // find if the element matches orientation selector(s) let media_transforms = []; Object.keys(orientationTransforms).forEach(key => { Object.keys(orientationTransforms[key]).forEach(tag => { - if (Object.keys(orientationTransforms[key][tag]).length > 0 && selectorMatchesElem(ruleContext, tag)) - media_transforms.push(orientationTransforms[key][tag].transform); + if (Object.keys(orientationTransforms[key][tag]).length > 0 && selectorMatchesElem(ruleContext, tag)) { + if (orientationTransforms[key][tag].transform) + media_transforms.push(orientationTransforms[key][tag].transform); + else + media_transforms.push(orientationTransforms[key][tag]); + } }); }); - console.log("node="+nodeName +", media_transforms="+JSON.stringify(media_transforms)); + // no match, the element is not in media orientation transform if (media_transforms.length === 0) return null; let ret = []; for (let i=0; i < media_transforms.length; i++) { - const media_transform = media_transforms[i]; + let media_transform = media_transforms[i]; + if (typeof media_transform === 'object') + for(var key in media_transform) + media_transform = key +"(" + media_transform[key] +")"; + let containsRotation = false; ['rotate', 'rotate3d', 'rotateZ', 'matrix', 'matrix3d'].forEach(rotation => { if (media_transform.includes(rotation)) containsRotation = true; @@ -104,11 +112,13 @@ export let element_orientation_unlocked: Rule = { */ if (definedStyle['transform']) { const page_degree = getRotationDegree(definedStyle['transform']); - degree -= page_degree; + // rotate is additive + degree += page_degree; } + // When degree is 1 turn (360 degree), it is not considered an orientation lock // allow 1 degree floating range for the right angle - if ((degree > 89 && degree < 91) || (degree > -91 && degree < -89)) + if (Math.abs(degree - 360) % 360 > 1) ret.push(RuleFail("fail_locked", [nodeName])); else ret.push(RulePass("pass")); } diff --git a/accessibility-checker-engine/src/v4/util/CSSUtil.ts b/accessibility-checker-engine/src/v4/util/CSSUtil.ts index 5fd21b3a6..0c7171f94 100644 --- a/accessibility-checker-engine/src/v4/util/CSSUtil.ts +++ b/accessibility-checker-engine/src/v4/util/CSSUtil.ts @@ -193,7 +193,7 @@ export function getDefinedStyles(elem: HTMLElement, pseudoClass?: string ) { */ export function getMediaOrientationTransform(doc: Document) { let orientationTransforms = {} - console.log("stylesheet="+JSON.stringify(doc.styleSheets)); + // Iterate through all of the stylesheets and rules for (let ssIndex = 0; ssIndex < doc.styleSheets.length; ++ssIndex) { const sheet = doc.styleSheets[ssIndex] as CSSStyleSheet; @@ -225,6 +225,8 @@ export function getMediaOrientationTransform(doc: Document) { } else { transforms[key] = styles[key]; } + } else if (key.toLocaleLowerCase() === "rotate") { + transforms[key] = styles[key]; } } elem_transforms[selector] = transforms; diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_accessiblename_exists_ruleunit/aria_imge.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_accessiblename_exists_ruleunit/aria_imge.html new file mode 100755 index 000000000..b5a5f36c3 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/aria_accessiblename_exists_ruleunit/aria_imge.html @@ -0,0 +1,42 @@ + + + + + + + + Test Suite + + + + + Home Navigation Bar + + + + + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-fail1.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-fail1.html index 5c2fb6680..84eb35f17 100644 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-fail1.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-fail1.html @@ -1,4 +1,4 @@ - + Page with some content - - Page Content +
+ Page Content
diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-pass3.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-pass3.html new file mode 100644 index 000000000..bf6ead37f --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_orientation_unlocked_ruleunit/act-pass3.html @@ -0,0 +1,40 @@ + + + Page with some content + + + +
+ Page Content +
+ + + \ No newline at end of file From 161259012586b198423803b06c65b600c5308161 Mon Sep 17 00:00:00 2001 From: nam-singh Date: Mon, 26 Aug 2024 21:49:39 +0530 Subject: [PATCH 060/161] adding id to link in reportTreeGrid --- .../src/ts/devtools/components/reportTreeGrid.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/accessibility-checker-extension/src/ts/devtools/components/reportTreeGrid.tsx b/accessibility-checker-extension/src/ts/devtools/components/reportTreeGrid.tsx index 30e7395b1..2d2d21a3a 100644 --- a/accessibility-checker-extension/src/ts/devtools/components/reportTreeGrid.tsx +++ b/accessibility-checker-extension/src/ts/devtools/components/reportTreeGrid.tsx @@ -837,6 +837,7 @@ export class ReportTreeGrid extends React.Component { this.onRow(group, thisIssue); From d754d2b557217eb7a1caec0f33dba6d5384b7acb Mon Sep 17 00:00:00 2001 From: nam-singh Date: Mon, 26 Aug 2024 22:11:29 +0530 Subject: [PATCH 061/161] stop propagation of containing div in reportTreeGrid --- .../src/ts/devtools/components/reportTreeGrid.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/accessibility-checker-extension/src/ts/devtools/components/reportTreeGrid.tsx b/accessibility-checker-extension/src/ts/devtools/components/reportTreeGrid.tsx index 2d2d21a3a..f028f0137 100644 --- a/accessibility-checker-extension/src/ts/devtools/components/reportTreeGrid.tsx +++ b/accessibility-checker-extension/src/ts/devtools/components/reportTreeGrid.tsx @@ -840,6 +840,7 @@ export class ReportTreeGrid extends React.Component { + evt.stopPropagation(); this.onRow(group, thisIssue); this.devtoolsAppController.setSecondaryView("help"); this.devtoolsAppController.openSecondary(`#${rowId} a`); From 048b680c4625f8196f6962428adad7049f36bddc Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 26 Aug 2024 13:31:02 -0500 Subject: [PATCH 062/161] Fix cypress baseline --- .../test/baselines/violations.json | 42 ++----------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/cypress-accessibility-checker/test/baselines/violations.json b/cypress-accessibility-checker/test/baselines/violations.json index 9d1b3891f..b5489abdf 100644 --- a/cypress-accessibility-checker/test/baselines/violations.json +++ b/cypress-accessibility-checker/test/baselines/violations.json @@ -107,39 +107,9 @@ "ignored": true, "level": "violation", "help": "https://able.ibm.com/rules/archives/2024.08.06/doc/en-US/img_alt_valid.html#%7B%22message%22%3A%22The%20image%20has%20neither%20an%20accessible%20name%20nor%20is%20marked%20as%20decorative%20or%20redundant%22%2C%22snippet%22%3A%22%3Cimg%20src%3D%5C%22missing-alt.jpg%5C%22%3E%22%2C%22value%22%3A%5B%22VIOLATION%22%2C%22FAIL%22%5D%2C%22reasonId%22%3A%22fail_no_alt%22%2C%22ruleId%22%3A%22img_alt_valid%22%2C%22msgArgs%22%3A%5B%5D%7D" - }, - { - "ruleId": "aria_accessiblename_exists", - "value": [ - "RECOMMENDATION", - "FAIL" - ], - "path": { - "dom": "/html[1]/body[1]/img[1]", - "aria": "/document[1]/img[1]" - }, - "ruleTime": 0, - "reasonId": "fail_no_accessible_name", - "message": "Element with \"img\" role has no accessible name", - "messageArgs": [ - "img", - "img" - ], - "apiArgs": [], - "bounds": { - "left": 16, - "top": 133, - "height": 32, - "width": 32 - }, - "snippet": "", - "category": "Accessibility", - "ignored": true, - "level": "recommendation", - "help": "https://able.ibm.com/rules/archives/2024.08.06/doc/en-US/aria_accessiblename_exists.html#%7B%22message%22%3A%22Element%20%3Cimg%3E%20with%20%5C%22img%5C%22%20role%20has%20no%20accessible%20name%22%2C%22snippet%22%3A%22%3Cimg%20src%3D%5C%22missing-alt.jpg%5C%22%3E%22%2C%22value%22%3A%5B%22RECOMMENDATION%22%2C%22FAIL%22%5D%2C%22reasonId%22%3A%22fail_no_accessible_name%22%2C%22ruleId%22%3A%22aria_accessiblename_exists%22%2C%22msgArgs%22%3A%5B%22img%22%2C%22img%22%5D%7D" } ], - "numExecuted": 31, + "numExecuted": 30, "ruleTime": 0, "nls": { "html_lang_exists": { @@ -154,10 +124,6 @@ "0": "Pages must provide a way to skip directly to the main content", "Fail_1": "The page does not provide a way to quickly navigate to the main content (ARIA \"main\" landmark or a skip link)" }, - "aria_accessiblename_exists": { - "0": "Elements with certain roles should have accessible names", - "fail_no_accessible_name": "Element <{0}> with \"{1}\" role has no accessible name" - }, "img_alt_valid": { "0": "Images must have accessible names unless they are decorative or redundant", "fail_no_alt": "The image has neither an accessible name nor is marked as decorative or redundant" @@ -171,7 +137,7 @@ "potentialrecommendation": 0, "manual": 0, "pass": 26, - "ignored": 5, + "ignored": 4, "elements": 7, "elementsViolation": 0, "elementsViolationReview": 0 @@ -188,10 +154,10 @@ "potentialrecommendation", "manual" ], - "startScan": 1723480681453, + "startScan": 1724696836617, "URL": "http://localhost:8080/test/sample-html/violations.html" }, - "scanID": "03c0fc62-453a-4b6c-a2b2-869c2818e5ea", + "scanID": "3287e266-6c7a-41d9-8e27-62d66146ad2b", "toolID": "cypress-accessibility-checker-v3.0.0", "label": "violations" } \ No newline at end of file From b6cbb5fb5d6db9c650afc81bb401c15dac1d3985 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 13:33:09 -0500 Subject: [PATCH 063/161] Bump axios from 1.7.3 to 1.7.4 in /rule-server (#1991) Bumps [axios](https://github.com/axios/axios) from 1.7.3 to 1.7.4. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.7.3...v1.7.4) --- updated-dependencies: - dependency-name: axios dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- rule-server/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rule-server/package-lock.json b/rule-server/package-lock.json index a2eaa89a8..628824afd 100644 --- a/rule-server/package-lock.json +++ b/rule-server/package-lock.json @@ -872,9 +872,9 @@ "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==" }, "node_modules/axios": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz", - "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "dev": true, "dependencies": { "follow-redirects": "^1.15.6", From 1f151daea9a01479653d8dc0d2641a120edcdd91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 13:33:30 -0500 Subject: [PATCH 064/161] Bump axios from 1.6.8 to 1.7.4 in /accessibility-checker-extension/test (#1990) Bumps [axios](https://github.com/axios/axios) from 1.6.8 to 1.7.4. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.6.8...v1.7.4) --- updated-dependencies: - dependency-name: axios dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ErickR <62436670+ErickRenteria@users.noreply.github.com> --- accessibility-checker-extension/test/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accessibility-checker-extension/test/package-lock.json b/accessibility-checker-extension/test/package-lock.json index 74b0184f6..5c044331b 100644 --- a/accessibility-checker-extension/test/package-lock.json +++ b/accessibility-checker-extension/test/package-lock.json @@ -984,9 +984,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "dev": true, "dependencies": { "follow-redirects": "^1.15.6", From 475f36db7e3f16290c184cc9a055122eec07b880 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:34:11 +0000 Subject: [PATCH 065/161] Bump micromatch from 4.0.7 to 4.0.8 in /report-react Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.7 to 4.0.8. - [Release notes](https://github.com/micromatch/micromatch/releases) - [Changelog](https://github.com/micromatch/micromatch/blob/4.0.8/CHANGELOG.md) - [Commits](https://github.com/micromatch/micromatch/compare/4.0.7...4.0.8) --- updated-dependencies: - dependency-name: micromatch dependency-type: indirect ... Signed-off-by: dependabot[bot] --- report-react/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/report-react/package-lock.json b/report-react/package-lock.json index 099bb6b83..4823faa97 100644 --- a/report-react/package-lock.json +++ b/report-react/package-lock.json @@ -10839,9 +10839,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -24482,9 +24482,9 @@ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "requires": { "braces": "^3.0.3", "picomatch": "^2.3.1" From 826031c3a79af3606939f481fc005d723b4e6ada Mon Sep 17 00:00:00 2001 From: Shunguo Date: Mon, 26 Aug 2024 13:35:09 -0500 Subject: [PATCH 066/161] update the rules #1958 --- .../src/v4/rules/img_alt_background.ts | 2 +- .../src/v4/rules/img_alt_decorative.ts | 2 +- .../src/v4/rules/img_alt_misuse.ts | 2 +- .../src/v4/rules/img_alt_null.ts | 2 +- .../src/v4/rules/img_alt_redundant.ts | 2 +- .../Baseline_aChecker.Baseline.html.json | 76 +++++-------------- 6 files changed, 26 insertions(+), 60 deletions(-) diff --git a/accessibility-checker-engine/src/v4/rules/img_alt_background.ts b/accessibility-checker-engine/src/v4/rules/img_alt_background.ts index d00ea245e..80e798982 100644 --- a/accessibility-checker-engine/src/v4/rules/img_alt_background.ts +++ b/accessibility-checker-engine/src/v4/rules/img_alt_background.ts @@ -11,7 +11,7 @@ limitations under the License. *****************************************************************************/ -import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule"; +import { Rule, RuleResult, RuleContext, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule"; import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { VisUtil } from "../../v2/dom/VisUtil"; diff --git a/accessibility-checker-engine/src/v4/rules/img_alt_decorative.ts b/accessibility-checker-engine/src/v4/rules/img_alt_decorative.ts index cb6aa874a..de3060d27 100644 --- a/accessibility-checker-engine/src/v4/rules/img_alt_decorative.ts +++ b/accessibility-checker-engine/src/v4/rules/img_alt_decorative.ts @@ -11,7 +11,7 @@ limitations under the License. *****************************************************************************/ -import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule"; +import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy } from "../api/IRule"; import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { RPTUtil } from "../../v2/checker/accessibility/util/legacy"; import { VisUtil } from "../../v2/dom/VisUtil"; diff --git a/accessibility-checker-engine/src/v4/rules/img_alt_misuse.ts b/accessibility-checker-engine/src/v4/rules/img_alt_misuse.ts index 2b778310c..821da0d63 100644 --- a/accessibility-checker-engine/src/v4/rules/img_alt_misuse.ts +++ b/accessibility-checker-engine/src/v4/rules/img_alt_misuse.ts @@ -11,7 +11,7 @@ limitations under the License. *****************************************************************************/ -import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule"; +import { Rule, RuleResult, RuleContext, RulePotential, RulePass, RuleContextHierarchy } from "../api/IRule"; import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { VisUtil } from "../../v2/dom/VisUtil"; diff --git a/accessibility-checker-engine/src/v4/rules/img_alt_null.ts b/accessibility-checker-engine/src/v4/rules/img_alt_null.ts index a879f9e5e..0abe9358c 100644 --- a/accessibility-checker-engine/src/v4/rules/img_alt_null.ts +++ b/accessibility-checker-engine/src/v4/rules/img_alt_null.ts @@ -11,7 +11,7 @@ limitations under the License. *****************************************************************************/ -import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule"; +import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy } from "../api/IRule"; import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { RPTUtil } from "../../v2/checker/accessibility/util/legacy"; import { VisUtil } from "../../v2/dom/VisUtil"; diff --git a/accessibility-checker-engine/src/v4/rules/img_alt_redundant.ts b/accessibility-checker-engine/src/v4/rules/img_alt_redundant.ts index 334f0628b..4df01e003 100644 --- a/accessibility-checker-engine/src/v4/rules/img_alt_redundant.ts +++ b/accessibility-checker-engine/src/v4/rules/img_alt_redundant.ts @@ -11,7 +11,7 @@ limitations under the License. *****************************************************************************/ -import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule"; +import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy } from "../api/IRule"; import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { NodeWalker, RPTUtil } from "../../v2/checker/accessibility/util/legacy"; diff --git a/accessibility-checker/test/baselines/Baseline_aChecker.Baseline.html.json b/accessibility-checker/test/baselines/Baseline_aChecker.Baseline.html.json index 3ecaefde0..d59eb3dd9 100644 --- a/accessibility-checker/test/baselines/Baseline_aChecker.Baseline.html.json +++ b/accessibility-checker/test/baselines/Baseline_aChecker.Baseline.html.json @@ -23,7 +23,7 @@ }, "snippet": "", "category": "Accessibility", - "ignored": false, + "ignored": true, "level": "violation", "help": "https://able.ibm.com/rules/archives/preview/doc/en-US/html_lang_exists.html#%7B%22message%22%3A%22Page%20detected%20as%20HTML%2C%20but%20does%20not%20have%20a%20'lang'%20attribute%22%2C%22snippet%22%3A%22%3Chtml%3E%22%2C%22value%22%3A%5B%22VIOLATION%22%2C%22FAIL%22%5D%2C%22reasonId%22%3A%22Fail_3%22%2C%22ruleId%22%3A%22html_lang_exists%22%2C%22msgArgs%22%3A%5B%5D%7D" }, @@ -50,7 +50,7 @@ }, "snippet": "", "category": "Accessibility", - "ignored": false, + "ignored": true, "level": "potentialviolation", "help": "https://able.ibm.com/rules/archives/preview/doc/en-US/html_skipnav_exists.html#%7B%22message%22%3A%22Verify%20there%20is%20a%20way%20to%20bypass%20blocks%20of%20content%20that%20are%20repeated%20on%20multiple%20Web%20pages%22%2C%22snippet%22%3A%22%3Chtml%3E%22%2C%22value%22%3A%5B%22VIOLATION%22%2C%22POTENTIAL%22%5D%2C%22reasonId%22%3A%22Potential_1%22%2C%22ruleId%22%3A%22html_skipnav_exists%22%2C%22msgArgs%22%3A%5B%5D%7D" }, @@ -77,7 +77,7 @@ }, "snippet": "", "category": "Accessibility", - "ignored": false, + "ignored": true, "level": "violation", "help": "https://able.ibm.com/rules/archives/preview/doc/en-US/page_title_exists.html#%7B%22message%22%3A%22Missing%20%3Ctitle%3E%20element%20in%20%3Chead%3E%20element%22%2C%22snippet%22%3A%22%3Chtml%3E%22%2C%22value%22%3A%5B%22VIOLATION%22%2C%22FAIL%22%5D%2C%22reasonId%22%3A%22Fail_2%22%2C%22ruleId%22%3A%22page_title_exists%22%2C%22msgArgs%22%3A%5B%5D%7D" }, @@ -91,7 +91,7 @@ "dom": "/html[1]", "aria": "/document[1]" }, - "ruleTime": 2, + "ruleTime": 1, "reasonId": "Pass_0", "message": "Rule Passed", "messageArgs": [], @@ -145,7 +145,7 @@ "dom": "/html[1]/head[1]", "aria": "/document[1]" }, - "ruleTime": 0, + "ruleTime": 1, "reasonId": "Pass_0", "message": "Rule Passed", "messageArgs": [], @@ -212,7 +212,7 @@ }, "snippet": "", "category": "Accessibility", - "ignored": false, + "ignored": true, "level": "violation", "help": "https://able.ibm.com/rules/archives/preview/doc/en-US/skip_main_exists.html#%7B%22message%22%3A%22The%20page%20does%20not%20provide%20a%20way%20to%20quickly%20navigate%20to%20the%20main%20content%20(ARIA%20%5C%22main%5C%22%20landmark%20or%20a%20skip%20link)%22%2C%22snippet%22%3A%22%3Cbody%3E%22%2C%22value%22%3A%5B%22VIOLATION%22%2C%22FAIL%22%5D%2C%22reasonId%22%3A%22Fail_1%22%2C%22ruleId%22%3A%22skip_main_exists%22%2C%22msgArgs%22%3A%5B%5D%7D" }, @@ -226,7 +226,7 @@ "dom": "/html[1]/body[1]", "aria": "/document[1]" }, - "ruleTime": 0, + "ruleTime": 1, "reasonId": "Pass_0", "message": "Rule Passed", "messageArgs": [], @@ -334,7 +334,7 @@ "dom": "/html[1]/body[1]/img[1]", "aria": "/document[1]/img[1]" }, - "ruleTime": 0, + "ruleTime": 1, "reasonId": "Pass_0", "message": "Rule Passed", "messageArgs": [], @@ -374,7 +374,7 @@ }, "snippet": "", "category": "Accessibility", - "ignored": false, + "ignored": true, "level": "violation", "help": "https://able.ibm.com/rules/archives/preview/doc/en-US/img_alt_valid.html#%7B%22message%22%3A%22The%20image%20has%20neither%20an%20accessible%20name%20nor%20is%20marked%20as%20decorative%20or%20redundant%22%2C%22snippet%22%3A%22%3Cimg%20id%3D%5C%22ace%5C%22%20src%3D%5C%22fail.png%5C%22%3E%22%2C%22value%22%3A%5B%22VIOLATION%22%2C%22FAIL%22%5D%2C%22reasonId%22%3A%22fail_no_alt%22%2C%22ruleId%22%3A%22img_alt_valid%22%2C%22msgArgs%22%3A%5B%5D%7D" }, @@ -513,36 +513,6 @@ "level": "pass", "help": "https://able.ibm.com/rules/archives/preview/doc/en-US/text_whitespace_valid.html#%7B%22message%22%3A%22Rule%20Passed%22%2C%22snippet%22%3A%22%3Cimg%20id%3D%5C%22ace%5C%22%20src%3D%5C%22fail.png%5C%22%3E%22%2C%22value%22%3A%5B%22VIOLATION%22%2C%22PASS%22%5D%2C%22reasonId%22%3A%22pass%22%2C%22ruleId%22%3A%22text_whitespace_valid%22%2C%22msgArgs%22%3A%5B%5D%7D" }, - { - "ruleId": "aria_accessiblename_exists", - "value": [ - "RECOMMENDATION", - "FAIL" - ], - "path": { - "dom": "/html[1]/body[1]/img[1]", - "aria": "/document[1]/img[1]" - }, - "ruleTime": 0, - "reasonId": "fail_no_accessible_name", - "message": "Element with \"img\" role has no accessible name", - "messageArgs": [ - "img", - "img" - ], - "apiArgs": [], - "bounds": { - "left": 8, - "top": 8, - "height": 0, - "width": 0 - }, - "snippet": "", - "category": "Accessibility", - "ignored": false, - "level": "recommendation", - "help": "https://able.ibm.com/rules/archives/preview/doc/en-US/aria_accessiblename_exists.html#%7B%22message%22%3A%22Element%20%3Cimg%3E%20with%20%5C%22img%5C%22%20role%20has%20no%20accessible%20name%22%2C%22snippet%22%3A%22%3Cimg%20id%3D%5C%22ace%5C%22%20src%3D%5C%22fail.png%5C%22%3E%22%2C%22value%22%3A%5B%22RECOMMENDATION%22%2C%22FAIL%22%5D%2C%22reasonId%22%3A%22fail_no_accessible_name%22%2C%22ruleId%22%3A%22aria_accessiblename_exists%22%2C%22msgArgs%22%3A%5B%22img%22%2C%22img%22%5D%7D" - }, { "ruleId": "aria_descendant_valid", "value": [ @@ -553,7 +523,7 @@ "dom": "/html[1]/body[1]/img[1]", "aria": "/document[1]/img[1]" }, - "ruleTime": 1, + "ruleTime": 0, "reasonId": "pass", "message": "The element contains valid descendants", "messageArgs": [], @@ -571,8 +541,8 @@ "help": "https://able.ibm.com/rules/archives/preview/doc/en-US/aria_descendant_valid.html#%7B%22message%22%3A%22The%20element%20contains%20valid%20descendants%22%2C%22snippet%22%3A%22%3Cimg%20id%3D%5C%22ace%5C%22%20src%3D%5C%22fail.png%5C%22%3E%22%2C%22value%22%3A%5B%22VIOLATION%22%2C%22PASS%22%5D%2C%22reasonId%22%3A%22pass%22%2C%22ruleId%22%3A%22aria_descendant_valid%22%2C%22msgArgs%22%3A%5B%5D%7D" } ], - "numExecuted": 21, - "ruleTime": 4, + "numExecuted": 20, + "ruleTime": 5, "nls": { "html_lang_exists": { "0": "Page must identify the default language of the document with a 'lang' attribute", @@ -618,10 +588,6 @@ "0": "Element 'id' attribute values must be unique within a document", "Pass_0": "Rule Passed" }, - "aria_accessiblename_exists": { - "0": "Elements with certain roles should have accessible names", - "fail_no_accessible_name": "Element <{0}> with \"{1}\" role has no accessible name" - }, "aria_descendant_valid": { "0": "Browsers ignore the explicit and implicit ARIA roles of the descendants of certain elements", "pass": "The element contains valid descendants" @@ -629,18 +595,18 @@ }, "summary": { "counts": { - "violation": 4, - "potentialviolation": 1, - "recommendation": 1, + "violation": 0, + "potentialviolation": 0, + "recommendation": 0, "potentialrecommendation": 0, "manual": 0, "pass": 15, - "ignored": 0, + "ignored": 5, "elements": 4, - "elementsViolation": 3, - "elementsViolationReview": 3 + "elementsViolation": 0, + "elementsViolationReview": 0 }, - "scanTime": 32, + "scanTime": 34, "ruleArchive": "Preview Rules (preview)", "policies": [ "IBM_Accessibility", @@ -654,10 +620,10 @@ "manual", "pass" ], - "startScan": 1716219646120, + "startScan": 1724686697450, "URL": "data:text/html;charset=utf-8,%3C!--%0A%20%20%20%20%20%2F******************************************************************************%0A%20%20%20%20%20Copyright%3A%3A%202020-%20IBM%2C%20Inc%0A%0A%20%20%20%20Licensed%20under%20the%20Apache%20License%2C%20Version%202.0%20(the%20%22License%22)%3B%0A%20%20%20%20you%20may%20not%20use%20this%20file%20except%20in%20compliance%20with%20the%20License.%0A%20%20%20%20You%20may%20obtain%20a%20copy%20of%20the%20License%20at%0A%0A%20%20%20%20http%3A%2F%2Fwww.apache.org%2Flicenses%2FLICENSE-2.0%0A%0A%20%20%20%20Unless%20required%20by%20applicable%20law%20or%20agreed%20to%20in%20writing%2C%20software%0A%20%20%20%20distributed%20under%20the%20License%20is%20distributed%20on%20an%20%22AS%20IS%22%20BASIS%2C%0A%20%20%20%20WITHOUT%20WARRANTIES%20OR%20CONDITIONS%20OF%20ANY%20KIND%2C%20either%20express%20or%20implied.%0A%20%20%20%20See%20the%20License%20for%20the%20specific%20language%20governing%20permissions%20and%0A%20%20%20%20limitations%20under%20the%20License.%0A%20%20*****************************************************************************%2F%0A%0A--%3E%20%20%20%20%0A%20%20%20%20%3Chtml%3E%0A%20%20%20%20%3Cbody%3E%0A%20%20%20%20%20%20%20%20%3Cimg%20src%3D%22fail.png%22%20id%3D%22ace%22%3E%0A%20%20%20%20%3C%2Fbody%3E%0A%3C%2Fhtml%3E" }, - "scanID": "e3856ce5-070e-4798-9dcc-9866c4468897", + "scanID": "5711a3a0-a763-4067-9eef-7f1db63cf8cb", "toolID": "accessibility-checker-v3.0.0", "label": "Baseline_aChecker.Baseline.html" } \ No newline at end of file From 734bfccb7f3a4399580d943d3cc6ad2fc79b8b73 Mon Sep 17 00:00:00 2001 From: Shunguo Date: Tue, 27 Aug 2024 10:38:07 -0500 Subject: [PATCH 067/161] update the img_alt_null rule #1958 --- .../src/v4/rules/img_alt_null.ts | 28 +++++++++------- .../Img-alt-arialabel.html | 33 +++++++++++++++++++ 2 files changed, 49 insertions(+), 12 deletions(-) create mode 100755 accessibility-checker-engine/test/v2/checker/accessibility/rules/img_alt_null_ruleunit/Img-alt-arialabel.html diff --git a/accessibility-checker-engine/src/v4/rules/img_alt_null.ts b/accessibility-checker-engine/src/v4/rules/img_alt_null.ts index 0abe9358c..80953a282 100644 --- a/accessibility-checker-engine/src/v4/rules/img_alt_null.ts +++ b/accessibility-checker-engine/src/v4/rules/img_alt_null.ts @@ -11,7 +11,7 @@ limitations under the License. *****************************************************************************/ -import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RuleContextHierarchy } from "../api/IRule"; +import { Rule, RuleResult, RuleFail, RuleContext, RulePass, RulePotential, RuleContextHierarchy } from "../api/IRule"; import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { RPTUtil } from "../../v2/checker/accessibility/util/legacy"; import { VisUtil } from "../../v2/dom/VisUtil"; @@ -21,21 +21,23 @@ export let img_alt_null: Rule = { context: "dom:img[alt]", refactor: { "WCAG20_Img_TitleEmptyWhenAltNull": { - "Pass_0": "Pass_0", - "Fail_1": "Fail_1"} + "Pass_0": "pass", + "Fail_1": "fail_decorative"} }, help: { "en-US": { - "Pass_0": "img_alt_null.html", - "Fail_1": "img_alt_null.html", + "pass": "img_alt_null.html", + "fail_decorative": "img_alt_null.html", + "fail_aria_override": "img_alt_null.html", "group": "img_alt_null.html" } }, messages: { "en-US": { - "Pass_0": "Rule Passed", - "Fail_1": "The image 'alt' attribute is empty, but the 'title' attribute is not empty", - "group": "When the image 'alt' attribute is empty, the 'title' attribute must also be empty" + "pass": "Neither 'aria' nor 'title' attributes are used for the decorative image", + "fail_decorative": "The image 'alt' attribute is empty, but the 'title' attribute is not empty", + "potential_aria_override": "The image 'alt' attribute is empty, but the 'aria' label is not empty and overrides the 'alt' attribute", + "group": "When the intent is to mark an image as decorative with an empty 'alt' attribute, the 'aria' or 'title' attributes should not be used" } }, rulesets: [{ @@ -44,7 +46,7 @@ export let img_alt_null: Rule = { "level": eRulePolicy.VIOLATION, "toolkitLevel": eToolkitLevel.LEVEL_ONE }], - act: [], + act: [{"46ca7f": {"potential_aria_override": "fail"}}], run: (context: RuleContext, options?: {}, contextHierarchies?: RuleContextHierarchy): RuleResult | RuleResult[] => { const ruleContext = context["dom"].node as Element; //skip the rule @@ -53,10 +55,12 @@ export let img_alt_null: Rule = { return null; } // We have a title, but alt is empty - if (RPTUtil.attributeNonEmpty(ruleContext, "title")) { - return RuleFail("Fail_1"); + if (RPTUtil.getAriaLabel(ruleContext).length > 0) { + return RulePotential("potential_aria_override"); + } else if (RPTUtil.attributeNonEmpty(ruleContext, "title")) { + return RuleFail("fail_decorative"); } else { - return RulePass("Pass_0"); + return RulePass("pass"); } } } \ No newline at end of file diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/img_alt_null_ruleunit/Img-alt-arialabel.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/img_alt_null_ruleunit/Img-alt-arialabel.html new file mode 100755 index 000000000..ca1c31b51 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/img_alt_null_ruleunit/Img-alt-arialabel.html @@ -0,0 +1,33 @@ + + + Failed Example + + + + + + + + From 821000a37543825844680f851289dff6680e2431 Mon Sep 17 00:00:00 2001 From: Shunguo Date: Tue, 27 Aug 2024 23:31:25 -0500 Subject: [PATCH 068/161] update the baselines #1958 --- .../aChecker.Scans/aChecker.Content.Puppeteer.test.js | 4 ++++ .../aChecker.Fast/aChecker.Scans/aChecker.Content.test.js | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.Puppeteer.test.js b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.Puppeteer.test.js index 8de6d3187..3a328e39c 100644 --- a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.Puppeteer.test.js +++ b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.Puppeteer.test.js @@ -120,6 +120,10 @@ var skipList = [ // TODO: temprarily ignore till the issue is resolved: https://github.com/IBMa/equal-access/issues/1932 path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "aria_attribute_conflict_ruleunit","aria-hidden.html"), + + // Puppeteer and embedded-chrome behave differently (?) + path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "element_orientation_unlocked_ruleunit","act-fail4.html"), + path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "element_orientation_unlocked_ruleunit","act-pass3.html") ] var skipMap = {} diff --git a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.test.js b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.test.js index 86147e1e8..6c047a436 100644 --- a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.test.js +++ b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.test.js @@ -106,7 +106,11 @@ var skipList = [ path.join(testRoot, "style_before_after_review_ruleunit", "D100.html"), // TODO: temprarily ignore till the issue is resolved: https://github.com/IBMa/equal-access/issues/1932 - path.join(testRoot, "aria_attribute_conflict_ruleunit","aria-hidden.html") + path.join(testRoot, "aria_attribute_conflict_ruleunit","aria-hidden.html"), + + // Puppeteer and embedded-chrome behave differently (?) + path.join(testRoot, "element_orientation_unlocked_ruleunit","act-fail4.html"), + path.join(testRoot, "element_orientation_unlocked_ruleunit","act-pass3.html") ] var skipMap = {} From 555ca5d8e4d5eea98f262d85aab29da8e801c9ff Mon Sep 17 00:00:00 2001 From: Shunguo Date: Wed, 28 Aug 2024 09:10:36 -0500 Subject: [PATCH 069/161] update the baselines #1958 --- .../aChecker.Scans/aChecker.Content.Puppeteer.test.js | 2 +- .../aChecker.Fast/aChecker.Scans/aChecker.Content.test.js | 2 +- .../mocha/aChecker.Fast/aChecker.Scans/aChecker.URL.test.js | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.Puppeteer.test.js b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.Puppeteer.test.js index 3a328e39c..2e2e69201 100644 --- a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.Puppeteer.test.js +++ b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.Puppeteer.test.js @@ -121,7 +121,7 @@ var skipList = [ // TODO: temprarily ignore till the issue is resolved: https://github.com/IBMa/equal-access/issues/1932 path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "aria_attribute_conflict_ruleunit","aria-hidden.html"), - // Puppeteer and embedded-chrome behave differently (?) + // Puppeteer and embedded-chrome @media css behave differently (?) path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "element_orientation_unlocked_ruleunit","act-fail4.html"), path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "element_orientation_unlocked_ruleunit","act-pass3.html") ] diff --git a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.test.js b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.test.js index 6c047a436..6dab68d37 100644 --- a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.test.js +++ b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.Content.test.js @@ -108,7 +108,7 @@ var skipList = [ // TODO: temprarily ignore till the issue is resolved: https://github.com/IBMa/equal-access/issues/1932 path.join(testRoot, "aria_attribute_conflict_ruleunit","aria-hidden.html"), - // Puppeteer and embedded-chrome behave differently (?) + // Puppeteer and embedded-chrome @media css behave differently (?) path.join(testRoot, "element_orientation_unlocked_ruleunit","act-fail4.html"), path.join(testRoot, "element_orientation_unlocked_ruleunit","act-pass3.html") ] diff --git a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.URL.test.js b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.URL.test.js index 1936812ef..3c9458084 100644 --- a/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.URL.test.js +++ b/accessibility-checker/test/mocha/aChecker.Fast/aChecker.Scans/aChecker.URL.test.js @@ -108,7 +108,11 @@ var skipList = [ path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "style_before_after_review_ruleunit","D100.html"), // TODO: temprarily ignore till the issue is resolved: https://github.com/IBMa/equal-access/issues/1932 - path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "aria_attribute_conflict_ruleunit","aria-hidden.html") + path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "aria_attribute_conflict_ruleunit","aria-hidden.html"), + + // Puppeteer and embedded-chrome @media css behave differently (?) + path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "element_orientation_unlocked_ruleunit","act-fail4.html"), + path.join(process.cwd(), "..", "accessibility-checker-engine", "test", "v2", "checker", "accessibility", "rules", "element_orientation_unlocked_ruleunit","act-pass3.html") ] var skipMap = {} From 932a63856e84d51f72ef79f3578cc4e949919a4f Mon Sep 17 00:00:00 2001 From: Shunguo Date: Wed, 28 Aug 2024 10:09:28 -0500 Subject: [PATCH 070/161] update the help reference #1958 --- accessibility-checker-engine/src/v4/rules/img_alt_null.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accessibility-checker-engine/src/v4/rules/img_alt_null.ts b/accessibility-checker-engine/src/v4/rules/img_alt_null.ts index 80953a282..d3e146e3a 100644 --- a/accessibility-checker-engine/src/v4/rules/img_alt_null.ts +++ b/accessibility-checker-engine/src/v4/rules/img_alt_null.ts @@ -28,7 +28,7 @@ export let img_alt_null: Rule = { "en-US": { "pass": "img_alt_null.html", "fail_decorative": "img_alt_null.html", - "fail_aria_override": "img_alt_null.html", + "potential_aria_override": "img_alt_null.html", "group": "img_alt_null.html" } }, From e5797a38b5d3ec60f5a4f6dfbab712b8a390fdc3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:15:36 +0000 Subject: [PATCH 071/161] Bump axios from 1.6.2 to 1.7.5 in /cypress-accessibility-checker Bumps [axios](https://github.com/axios/axios) from 1.6.2 to 1.7.5. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.6.2...v1.7.5) --- updated-dependencies: - dependency-name: axios dependency-type: indirect ... Signed-off-by: dependabot[bot] --- cypress-accessibility-checker/package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cypress-accessibility-checker/package-lock.json b/cypress-accessibility-checker/package-lock.json index 907868c68..fcbcfd3b6 100644 --- a/cypress-accessibility-checker/package-lock.json +++ b/cypress-accessibility-checker/package-lock.json @@ -582,12 +582,12 @@ "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", + "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } From ef240905b3136782754aabb3cd71d79cfaaa10a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:15:47 +0000 Subject: [PATCH 072/161] Bump webpack from 5.79.0 to 5.94.0 in /accessibility-checker-extension Bumps [webpack](https://github.com/webpack/webpack) from 5.79.0 to 5.94.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.79.0...v5.94.0) --- updated-dependencies: - dependency-name: webpack dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- .../package-lock.json | 686 +++++++++--------- accessibility-checker-extension/package.json | 2 +- 2 files changed, 331 insertions(+), 357 deletions(-) diff --git a/accessibility-checker-extension/package-lock.json b/accessibility-checker-extension/package-lock.json index e6a8cd81f..c581bf354 100644 --- a/accessibility-checker-extension/package-lock.json +++ b/accessibility-checker-extension/package-lock.json @@ -54,7 +54,7 @@ "url-loader": "^4.1.1", "use-resize-observer": "^8.0.0", "web-ext": "^8.0.0", - "webpack": "^5.79.0", + "webpack": "^5.94.0", "webpack-cli": "^4.9.1", "webpack-ext-reloader": "^1.1.9" } @@ -2351,30 +2351,30 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -2386,9 +2386,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -2798,28 +2798,10 @@ "@types/har-format": "*" } }, - "node_modules/@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/filesystem": { "version": "0.0.32", @@ -3013,133 +2995,133 @@ "dev": true }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dependencies": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, @@ -3248,10 +3230,10 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "peerDependencies": { "acorn": "^8" } @@ -3992,9 +3974,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "funding": [ { "type": "opencollective", @@ -4003,13 +3985,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -4171,9 +4157,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001467", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001467.tgz", - "integrity": "sha512-cEdN/5e+RPikvl9AHm4uuLXxeCNq8rFsQ+lPHTfe/OtypP3WwnVVbjn+6uBV7PaFL6xUFzTh+sSCOz1rKhcO+Q==", + "version": "1.0.30001653", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz", + "integrity": "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==", "funding": [ { "type": "opencollective", @@ -4182,6 +4168,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -5648,9 +5638,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.332", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.332.tgz", - "integrity": "sha512-c1Vbv5tuUlBFp0mb3mCIjw+REEsgthRgNE8BlbEDKmvzb8rxjcVki6OkQP83vLN34s0XCxpSkq7AZNep1a6xhw==" + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", + "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -5676,9 +5666,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -5732,9 +5722,9 @@ "dev": true }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "engines": { "node": ">=6" } @@ -8505,9 +8495,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -9079,9 +9069,9 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -10859,12 +10849,12 @@ } }, "node_modules/terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "version": "5.31.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", + "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -10876,15 +10866,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" + "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" @@ -11455,9 +11445,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "funding": [ { "type": "opencollective", @@ -11466,14 +11456,18 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -11918,33 +11912,32 @@ "dev": true }, "node_modules/webpack": { - "version": "5.79.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.79.0.tgz", - "integrity": "sha512-3mN4rR2Xq+INd6NnYuL9RC9GAmc1ROPKJoHhrZ4pAjdMFEkJJWrsPw8o2JjCIyQyTu7rTXYn4VG6OpyB3CobZg==", - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "dependencies": { + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -12136,9 +12129,9 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -14178,27 +14171,27 @@ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" }, "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" }, "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" }, "dependencies": { "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } } } @@ -14209,9 +14202,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "requires": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -14467,28 +14460,10 @@ "@types/har-format": "*" } }, - "@types/eslint": { - "version": "8.21.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", - "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, "@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "@types/filesystem": { "version": "0.0.32", @@ -14680,133 +14655,133 @@ "dev": true }, "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" } }, "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" } }, "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" } }, "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "requires": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, @@ -14889,10 +14864,10 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==" }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "requires": {} }, "acorn-jsx": { @@ -15433,14 +15408,14 @@ } }, "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" } }, "buffer": { @@ -15543,9 +15518,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001467", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001467.tgz", - "integrity": "sha512-cEdN/5e+RPikvl9AHm4uuLXxeCNq8rFsQ+lPHTfe/OtypP3WwnVVbjn+6uBV7PaFL6xUFzTh+sSCOz1rKhcO+Q==" + "version": "1.0.30001653", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz", + "integrity": "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==" }, "chainsaw": { "version": "0.1.0", @@ -16648,9 +16623,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.332", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.332.tgz", - "integrity": "sha512-c1Vbv5tuUlBFp0mb3mCIjw+REEsgthRgNE8BlbEDKmvzb8rxjcVki6OkQP83vLN34s0XCxpSkq7AZNep1a6xhw==" + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", + "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==" }, "emoji-regex": { "version": "9.2.2", @@ -16673,9 +16648,9 @@ } }, "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -16714,9 +16689,9 @@ "dev": true }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==" }, "escape-goat": { "version": "4.0.0", @@ -18776,9 +18751,9 @@ } }, "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "normalize-path": { "version": "3.0.0", @@ -19186,9 +19161,9 @@ "dev": true }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "picomatch": { "version": "2.3.1", @@ -20472,12 +20447,12 @@ } }, "terser": { - "version": "5.16.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", - "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "version": "5.31.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", + "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -20490,15 +20465,15 @@ } }, "terser-webpack-plugin": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", - "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "requires": { - "@jridgewell/trace-mapping": "^0.3.17", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", - "terser": "^5.16.5" + "terser": "^5.26.0" }, "dependencies": { "ajv": { @@ -20920,12 +20895,12 @@ "dev": true }, "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" } }, "update-notifier": { @@ -21257,33 +21232,32 @@ "dev": true }, "webpack": { - "version": "5.79.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.79.0.tgz", - "integrity": "sha512-3mN4rR2Xq+INd6NnYuL9RC9GAmc1ROPKJoHhrZ4pAjdMFEkJJWrsPw8o2JjCIyQyTu7rTXYn4VG6OpyB3CobZg==", - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "requires": { + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.2.0", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "dependencies": { @@ -21324,9 +21298,9 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "requires": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", diff --git a/accessibility-checker-extension/package.json b/accessibility-checker-extension/package.json index 17fada385..0bd1efd4e 100644 --- a/accessibility-checker-extension/package.json +++ b/accessibility-checker-extension/package.json @@ -62,7 +62,7 @@ "url-loader": "^4.1.1", "use-resize-observer": "^8.0.0", "web-ext": "^8.0.0", - "webpack": "^5.79.0", + "webpack": "^5.94.0", "webpack-cli": "^4.9.1", "webpack-ext-reloader": "^1.1.9" }, From dbea238a0027054e7059e01f723b270ed55aabbd Mon Sep 17 00:00:00 2001 From: Erick Renteria Date: Thu, 29 Aug 2024 21:09:51 -0500 Subject: [PATCH 073/161] Rule server for 8-30 --- rule-server/src/static/archives.json | 11 +- .../2024.08.29/doc/assets/NeedsReview16.svg | 25 + .../doc/assets/Recommendation16.svg | 15 + .../2024.08.29/doc/assets/Violation16.svg | 13 + .../archives/2024.08.29/doc/common/help.css | 268 + .../archives/2024.08.29/doc/common/help.js | 225 + .../archives/2024.08.29/doc/common/rules.css | 29 + .../en-US/IBMA_Color_Contrast_WCAG2AA_PV.html | 90 + .../Rpt_Aria_ArticleRoleLabel_Implicit.html | 95 + .../Rpt_Aria_GroupRoleLabel_Implicit.html | 107 + .../doc/en-US/a_target_warning.html | 91 + .../2024.08.29/doc/en-US/a_text_purpose.html | 108 + .../doc/en-US/applet_alt_exists.html | 103 + .../en-US/application_content_accessible.html | 97 + .../2024.08.29/doc/en-US/area_alt_exists.html | 101 + .../doc/en-US/aria_accessiblename_exists.html | 112 + .../aria_activedescendant_tabindex_valid.html | 107 + .../en-US/aria_activedescendant_valid.html | 103 + .../en-US/aria_application_label_unique.html | 103 + .../doc/en-US/aria_application_labelled.html | 100 + .../doc/en-US/aria_article_label_unique.html | 104 + .../doc/en-US/aria_attribute_allowed.html | 97 + .../doc/en-US/aria_attribute_conflict.html | 109 + .../doc/en-US/aria_attribute_deprecated.html | 103 + .../doc/en-US/aria_attribute_exists.html | 93 + .../doc/en-US/aria_attribute_redundant.html | 98 + .../doc/en-US/aria_attribute_required.html | 106 + .../doc/en-US/aria_attribute_valid.html | 102 + .../doc/en-US/aria_attribute_value_valid.html | 94 + .../doc/en-US/aria_banner_label_unique.html | 104 + .../doc/en-US/aria_banner_single.html | 98 + .../doc/en-US/aria_child_tabbable.html | 98 + .../doc/en-US/aria_child_valid.html | 121 + .../aria_complementary_label_unique.html | 103 + .../aria_complementary_label_visible.html | 100 + .../en-US/aria_complementary_labelled.html | 100 + .../doc/en-US/aria_content_in_landmark.html | 92 + .../en-US/aria_contentinfo_label_unique.html | 104 + .../doc/en-US/aria_contentinfo_misuse.html | 105 + .../doc/en-US/aria_contentinfo_single.html | 100 + .../doc/en-US/aria_descendant_valid.html | 101 + .../doc/en-US/aria_document_label_unique.html | 91 + .../en-US/aria_eventhandler_role_valid.html | 92 + .../doc/en-US/aria_form_label_unique.html | 112 + .../doc/en-US/aria_graphic_labelled.html | 99 + .../doc/en-US/aria_hidden_nontabbable.html | 113 + .../2024.08.29/doc/en-US/aria_id_unique.html | 98 + .../doc/en-US/aria_img_labelled.html | 100 + .../en-US/aria_keyboard_handler_exists.html | 103 + .../doc/en-US/aria_landmark_name_unique.html | 110 + .../doc/en-US/aria_main_label_unique.html | 111 + .../doc/en-US/aria_main_label_visible.html | 102 + .../en-US/aria_navigation_label_unique.html | 106 + .../doc/en-US/aria_parent_required.html | 98 + .../doc/en-US/aria_region_label_unique.html | 102 + .../doc/en-US/aria_region_labelled.html | 102 + .../doc/en-US/aria_role_allowed.html | 105 + .../doc/en-US/aria_role_redundant.html | 107 + .../2024.08.29/doc/en-US/aria_role_valid.html | 90 + .../doc/en-US/aria_search_label_unique.html | 100 + .../doc/en-US/aria_toolbar_label_unique.html | 102 + .../doc/en-US/aria_widget_labelled.html | 102 + .../doc/en-US/asciiart_alt_exists.html | 91 + .../doc/en-US/blink_css_review.html | 94 + .../doc/en-US/blink_elem_deprecated.html | 94 + .../doc/en-US/blockquote_cite_exists.html | 91 + .../doc/en-US/canvas_content_described.html | 115 + .../doc/en-US/caption_track_exists.html | 100 + .../doc/en-US/combobox_active_descendant.html | 109 + .../en-US/combobox_autocomplete_valid.html | 136 + .../doc/en-US/combobox_design_valid.html | 93 + .../en-US/combobox_focusable_elements.html | 92 + .../doc/en-US/combobox_haspopup_valid.html | 107 + .../doc/en-US/combobox_popup_reference.html | 109 + .../doc/en-US/dir_attribute_valid.html | 89 + .../en-US/download_keyboard_controllable.html | 92 + .../en-US/draggable_alternative_exists.html | 105 + .../doc/en-US/element_accesskey_labelled.html | 97 + .../doc/en-US/element_accesskey_unique.html | 100 + .../en-US/element_attribute_deprecated.html | 103 + .../doc/en-US/element_id_unique.html | 102 + .../doc/en-US/element_lang_valid.html | 108 + .../en-US/element_mouseevent_keyboard.html | 102 + .../en-US/element_orientation_unlocked.html | 112 + .../en-US/element_scrollable_tabbable.html | 115 + .../en-US/element_tabbable_role_valid.html | 136 + .../en-US/element_tabbable_unobscured.html | 103 + .../doc/en-US/element_tabbable_visible.html | 124 + .../doc/en-US/embed_alt_exists.html | 95 + .../doc/en-US/embed_noembed_exists.html | 102 + .../doc/en-US/emoticons_alt_exists.html | 91 + .../doc/en-US/error_message_exists.html | 105 + .../doc/en-US/fieldset_label_valid.html | 106 + .../doc/en-US/fieldset_legend_valid.html | 101 + .../doc/en-US/figure_label_exists.html | 104 + .../2024.08.29/doc/en-US/form_font_color.html | 90 + .../doc/en-US/form_interaction_review.html | 92 + .../doc/en-US/form_label_unique.html | 90 + .../doc/en-US/form_submit_button_exists.html | 92 + .../doc/en-US/form_submit_review.html | 93 + .../2024.08.29/doc/en-US/frame_src_valid.html | 95 + .../doc/en-US/frame_title_exists.html | 99 + .../doc/en-US/heading_content_exists.html | 89 + .../doc/en-US/heading_markup_misuse.html | 92 + .../doc/en-US/html_lang_exists.html | 92 + .../2024.08.29/doc/en-US/html_lang_valid.html | 111 + .../doc/en-US/html_skipnav_exists.html | 91 + .../en-US/iframe_interactive_tabbable.html | 105 + .../doc/en-US/imagebutton_alt_exists.html | 90 + .../doc/en-US/imagemap_alt_exists.html | 101 + .../doc/en-US/img_alt_background.html | 90 + .../doc/en-US/img_alt_decorative.html | 93 + .../2024.08.29/doc/en-US/img_alt_misuse.html | 91 + .../2024.08.29/doc/en-US/img_alt_null.html | 94 + .../doc/en-US/img_alt_redundant.html | 94 + .../2024.08.29/doc/en-US/img_alt_valid.html | 99 + .../doc/en-US/img_ismap_misuse.html | 91 + .../doc/en-US/img_longdesc_misuse.html | 98 + .../doc/en-US/input_autocomplete_valid.html | 121 + .../doc/en-US/input_checkboxes_grouped.html | 90 + .../doc/en-US/input_fields_grouped.html | 104 + .../doc/en-US/input_haspopup_conflict.html | 120 + .../doc/en-US/input_label_after.html | 98 + .../doc/en-US/input_label_before.html | 99 + .../doc/en-US/input_label_exists.html | 94 + .../doc/en-US/input_label_visible.html | 127 + .../doc/en-US/input_onchange_review.html | 103 + .../input_placeholder_label_visible.html | 107 + .../doc/en-US/label_content_exists.html | 90 + .../doc/en-US/label_name_visible.html | 97 + .../2024.08.29/doc/en-US/label_ref_valid.html | 97 + .../doc/en-US/list_children_valid.html | 111 + .../doc/en-US/list_markup_review.html | 91 + .../doc/en-US/list_structure_proper.html | 89 + .../doc/en-US/marquee_elem_avoid.html | 94 + .../2024.08.29/doc/en-US/media_alt_brief.html | 111 + .../doc/en-US/media_alt_exists.html | 95 + .../doc/en-US/media_audio_transcribed.html | 97 + .../en-US/media_autostart_controllable.html | 93 + .../en-US/media_keyboard_controllable.html | 111 + .../doc/en-US/media_live_captioned.html | 91 + .../doc/en-US/media_track_available.html | 96 + .../doc/en-US/meta_redirect_optional.html | 94 + .../doc/en-US/meta_refresh_delay.html | 95 + .../doc/en-US/meta_viewport_zoomable.html | 98 + .../doc/en-US/noembed_content_exists.html | 100 + .../doc/en-US/object_text_exists.html | 101 + .../doc/en-US/page_title_exists.html | 103 + .../doc/en-US/page_title_valid.html | 105 + .../doc/en-US/script_focus_blur_review.html | 96 + .../doc/en-US/script_onclick_avoid.html | 92 + .../doc/en-US/script_onclick_misuse.html | 92 + .../doc/en-US/script_select_review.html | 97 + .../doc/en-US/select_options_grouped.html | 90 + .../doc/en-US/skip_main_described.html | 100 + .../doc/en-US/skip_main_exists.html | 103 + .../en-US/style_background_decorative.html | 93 + .../doc/en-US/style_before_after_review.html | 95 + .../doc/en-US/style_color_misuse.html | 89 + .../doc/en-US/style_focus_visible.html | 97 + .../doc/en-US/style_highcontrast_visible.html | 100 + .../doc/en-US/style_hover_persistent.html | 118 + .../doc/en-US/style_viewport_resizable.html | 93 + .../doc/en-US/svg_graphics_labelled.html | 127 + .../doc/en-US/table_aria_descendants.html | 110 + .../doc/en-US/table_caption_empty.html | 101 + .../doc/en-US/table_caption_nested.html | 98 + .../doc/en-US/table_headers_exists.html | 93 + .../doc/en-US/table_headers_ref_valid.html | 91 + .../doc/en-US/table_headers_related.html | 91 + .../doc/en-US/table_layout_linearized.html | 92 + .../doc/en-US/table_scope_valid.html | 93 + .../doc/en-US/table_structure_misuse.html | 91 + .../doc/en-US/table_summary_redundant.html | 101 + .../doc/en-US/target_spacing_sufficient.html | 108 + .../doc/en-US/text_block_heading.html | 92 + .../doc/en-US/text_contrast_sufficient.html | 92 + .../doc/en-US/text_quoted_correctly.html | 106 + .../doc/en-US/text_sensory_misuse.html | 96 + .../doc/en-US/text_spacing_valid.html | 103 + .../doc/en-US/text_whitespace_valid.html | 93 + .../doc/en-US/widget_tabbable_exists.html | 98 + .../doc/en-US/widget_tabbable_single.html | 96 + .../static/archives/2024.08.29/doc/rules.html | 20112 ++++++++++ .../archives/2024.08.29/js/ace-debug.js | 30682 ++++++++++++++++ .../archives/2024.08.29/js/ace-node-debug.js | 30080 +++++++++++++++ .../static/archives/2024.08.29/js/ace-node.js | 2 + .../2024.08.29/js/ace-node.js.LICENSE.txt | 15 + .../src/static/archives/2024.08.29/js/ace.js | 2 + .../archives/2024.08.29/js/ace.js.LICENSE.txt | 15 + 190 files changed, 99129 insertions(+), 3 deletions(-) create mode 100644 rule-server/src/static/archives/2024.08.29/doc/assets/NeedsReview16.svg create mode 100644 rule-server/src/static/archives/2024.08.29/doc/assets/Recommendation16.svg create mode 100644 rule-server/src/static/archives/2024.08.29/doc/assets/Violation16.svg create mode 100644 rule-server/src/static/archives/2024.08.29/doc/common/help.css create mode 100644 rule-server/src/static/archives/2024.08.29/doc/common/help.js create mode 100644 rule-server/src/static/archives/2024.08.29/doc/common/rules.css create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/IBMA_Color_Contrast_WCAG2AA_PV.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/Rpt_Aria_ArticleRoleLabel_Implicit.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/Rpt_Aria_GroupRoleLabel_Implicit.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/a_target_warning.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/a_text_purpose.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/applet_alt_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/application_content_accessible.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/area_alt_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_accessiblename_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_activedescendant_tabindex_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_activedescendant_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_application_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_application_labelled.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_article_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_allowed.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_conflict.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_deprecated.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_redundant.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_required.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_value_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_banner_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_banner_single.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_child_tabbable.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_child_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_label_visible.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_labelled.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_content_in_landmark.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_misuse.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_single.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_descendant_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_document_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_eventhandler_role_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_form_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_graphic_labelled.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_hidden_nontabbable.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_id_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_img_labelled.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_keyboard_handler_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_landmark_name_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_main_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_main_label_visible.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_navigation_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_parent_required.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_region_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_region_labelled.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_allowed.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_redundant.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_search_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_toolbar_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/aria_widget_labelled.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/asciiart_alt_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/blink_css_review.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/blink_elem_deprecated.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/blockquote_cite_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/canvas_content_described.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/caption_track_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_active_descendant.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_autocomplete_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_design_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_focusable_elements.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_haspopup_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_popup_reference.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/dir_attribute_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/download_keyboard_controllable.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/draggable_alternative_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_accesskey_labelled.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_accesskey_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_attribute_deprecated.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_id_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_lang_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_mouseevent_keyboard.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_orientation_unlocked.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_scrollable_tabbable.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_role_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_unobscured.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_visible.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/embed_alt_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/embed_noembed_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/emoticons_alt_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/error_message_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/fieldset_label_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/fieldset_legend_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/figure_label_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/form_font_color.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/form_interaction_review.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/form_label_unique.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/form_submit_button_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/form_submit_review.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/frame_src_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/frame_title_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/heading_content_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/heading_markup_misuse.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/html_lang_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/html_lang_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/html_skipnav_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/iframe_interactive_tabbable.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/imagebutton_alt_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/imagemap_alt_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_background.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_decorative.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_misuse.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_null.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_redundant.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/img_ismap_misuse.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/img_longdesc_misuse.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_autocomplete_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_checkboxes_grouped.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_fields_grouped.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_haspopup_conflict.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_after.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_before.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_visible.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_onchange_review.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/input_placeholder_label_visible.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/label_content_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/label_name_visible.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/label_ref_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/list_children_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/list_markup_review.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/list_structure_proper.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/marquee_elem_avoid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/media_alt_brief.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/media_alt_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/media_audio_transcribed.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/media_autostart_controllable.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/media_keyboard_controllable.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/media_live_captioned.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/media_track_available.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/meta_redirect_optional.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/meta_refresh_delay.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/meta_viewport_zoomable.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/noembed_content_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/object_text_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/page_title_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/page_title_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/script_focus_blur_review.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/script_onclick_avoid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/script_onclick_misuse.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/script_select_review.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/select_options_grouped.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/skip_main_described.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/skip_main_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/style_background_decorative.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/style_before_after_review.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/style_color_misuse.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/style_focus_visible.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/style_highcontrast_visible.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/style_hover_persistent.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/style_viewport_resizable.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/svg_graphics_labelled.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_aria_descendants.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_caption_empty.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_caption_nested.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_ref_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_related.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_layout_linearized.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_scope_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_structure_misuse.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/table_summary_redundant.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/target_spacing_sufficient.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/text_block_heading.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/text_contrast_sufficient.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/text_quoted_correctly.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/text_sensory_misuse.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/text_spacing_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/text_whitespace_valid.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/widget_tabbable_exists.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/en-US/widget_tabbable_single.html create mode 100644 rule-server/src/static/archives/2024.08.29/doc/rules.html create mode 100644 rule-server/src/static/archives/2024.08.29/js/ace-debug.js create mode 100644 rule-server/src/static/archives/2024.08.29/js/ace-node-debug.js create mode 100644 rule-server/src/static/archives/2024.08.29/js/ace-node.js create mode 100644 rule-server/src/static/archives/2024.08.29/js/ace-node.js.LICENSE.txt create mode 100644 rule-server/src/static/archives/2024.08.29/js/ace.js create mode 100644 rule-server/src/static/archives/2024.08.29/js/ace.js.LICENSE.txt diff --git a/rule-server/src/static/archives.json b/rule-server/src/static/archives.json index 768a8a11e..242a0617d 100644 --- a/rule-server/src/static/archives.json +++ b/rule-server/src/static/archives.json @@ -3,7 +3,13 @@ "id": "latest", "name": "Latest Deployment", "path": "/archives/latest" - }, + }, + { + "id": "29August2024", + "name": "29 August 2024 Deployment (IBM 7.2, 7.3)", + "version": "3.1.75", + "path": "/archives/2024.08.29" + }, { "id": "06August2024", "name": "06 August 2024 Deployment (IBM 7.2, 7.3)", @@ -213,7 +219,6 @@ "name": "17 November 2021 Deployment (IBM 7.2)", "version": "3.1.12", "path": "/archives/2021.11.17" - }, { "id": "25Oct2021", @@ -292,4 +297,4 @@ "name": "Preview Rules", "path": "/archives/preview" } -] +] \ No newline at end of file diff --git a/rule-server/src/static/archives/2024.08.29/doc/assets/NeedsReview16.svg b/rule-server/src/static/archives/2024.08.29/doc/assets/NeedsReview16.svg new file mode 100644 index 000000000..917834a38 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/assets/NeedsReview16.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/rule-server/src/static/archives/2024.08.29/doc/assets/Recommendation16.svg b/rule-server/src/static/archives/2024.08.29/doc/assets/Recommendation16.svg new file mode 100644 index 000000000..b57dc73d5 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/assets/Recommendation16.svg @@ -0,0 +1,15 @@ + + + + + + +i + diff --git a/rule-server/src/static/archives/2024.08.29/doc/assets/Violation16.svg b/rule-server/src/static/archives/2024.08.29/doc/assets/Violation16.svg new file mode 100644 index 000000000..5f8c9c710 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/assets/Violation16.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/rule-server/src/static/archives/2024.08.29/doc/common/help.css b/rule-server/src/static/archives/2024.08.29/doc/common/help.css new file mode 100644 index 000000000..0db9f74b4 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/common/help.css @@ -0,0 +1,268 @@ +/****************************************************************************** + Copyright:: 2022- IBM, Inc + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +@import url("https://1.www.s81c.com/common/carbon-for-ibm-dotcom/tag/v1/latest/plex.css"); +@import url('https://unpkg.com/carbon-components/css/carbon-components.min.css'); +@import url("https://1.www.s81c.com/common/carbon-for-ibm-dotcom/tag/v1/latest/themes.css"); + +bx-list-item>code, p>code, td>code { + background-color: var(--cds-layer); + border-radius: 4px; + bottom: 0.0625em; + color: var(--cds-text-primary); + display: inline; + font-size: .75rem; + font-size: .875em; + font-weight: 400; + letter-spacing: .32px; + line-height: 1.33333; + padding: 0 0.5em; + position: relative; +} + +.toolHelp a { + color: var(--cds-link-primary) +} + +.toolHelp .toolMain p ~ p { + margin-top: .5rem; +} + +.toolHelp .toolHead h3 { + font-family: 'IBM Plex Sans','Helvetica Neue',Arial,sans-serif; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 24px; +} + +.toolHelp .toolHead .issueLevel { + font-family: 'IBM Plex Sans','Helvetica Neue',Arial,sans-serif; + font-style: normal; + font-weight: 400; + font-size: 12px; + line-height: 16px; +} + +.toolHelp .toolHead #ruleMessage { + font-family: 'IBM Plex Sans','Helvetica Neue',Arial,sans-serif; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 24px; + margin-top: .5rem; + margin-bottom: .5rem; +} + +.toolHelp .toolHead #groupLabel { + font-family: 'IBM Plex Sans','Helvetica Neue',Arial,sans-serif; + font-style: normal; + font-weight: 400; + font-size: 12px; + line-height: 16px; +} + +/* productive-heading-03 */ +.toolHelp .toolMain h3 { + font-family: 'IBM Plex Sans','Helvetica Neue',Arial,sans-serif; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 24px; +} + +.toolHelp .toolSide .bx--list__item { + color: black; + font-size: 0.875rem; + line-height: 18px; +} + +/* productive-heading-03 */ +.toolHelp .toolSide h3 { + font-family: 'IBM Plex Sans','Helvetica Neue',Arial,sans-serif; + font-style: normal; + font-weight: 600; + font-size: 16px; + line-height: 24px; +} + +@media (min-width: 42rem) { + html, body, .toolHelp .bx--row:nth-child(2) { + height: 100%; + } +} +body { + font-family: 'IBM Plex Sans','Helvetica Neue',Arial,sans-serif; + color: var(--cds-text-primary); + background-color: var(--cds-ui-background); +} + +.toolHelp { + padding: 0px; + margin: 0px; + max-width: 100%; + background-color: #e8daff; +} + +.toolHelp p { + font-family: 'IBM Plex Sans','Helvetica Neue',Arial,sans-serif; +font-style: normal; +font-weight: 400; +font-size: 14px; +line-height: 20px; +/* or 143% */ + +letter-spacing: 0.16px; +} + +.dds-theme-zone-g90 .toolHelp { + background-color: #31135E; +} + +.toolHelp .bx--row { + margin: 0px; +} + +.toolHelp .toolHead { + margin-bottom: 1rem; + padding-top: 1rem; +} +.toolHelp .toolMain { + background-color: var(--cds-ui-background); + padding-top: 1rem; + padding-bottom: 1rem; + border-top: solid var(--cds-text-primary) 1px; +} +.toolHelp .toolMain h2 { + margin-top: 32px; + margin-bottom: 0.5rem; +} +.toolHelp .toolMain h3 { + margin-top: 1.5rem; + margin-bottom: 0.5rem; +} +.toolHelp .toolMain p { + margin-top: 0px; +} + +.toolHelp .toolSide { + padding: 16px 16px 16px 32px; + background-color: var(--cds-ui-background); + color: var(--cds-text-primary); + border-top: solid var(--cds-text-primary) 1px; +} +@media (min-width: 42rem) { + .toolHelp .toolSide { + border-left: solid var(--cds-text-primary) 1px; + } +} + +.toolHelp .toolSide h2 { + margin-top: 32px; + margin-bottom: 0.5rem; +} +.toolHelp .toolSide h3 { + margin-top: 1.5rem; + margin-bottom: 0.5rem; +} +.toolHelp .toolSide p { + margin-top: 0px; +} +@media (min-width: 66rem) { + .toolHelp .toolMain p, bx-list-item { + max-width: 66.66%; + } +} +bx-code-snippet[type="multi"]::after { + height: 0px; +} + +#ruleInfo { + margin-top: 1rem; +} + +#ruleInfo p { + font-size: 14px; +} + +mark-down table tbody tr:hover { + background: var(--cds-layer-hover); +} +mark-down table tbody tr:hover td, mark-down table tbody tr:hover th { + background: var(--cds-layer-hover); + -webkit-border-after: 1px solid var(--cds-layer-hover); + border-block-end: 1px solid var(--cds-layer-hover); + -webkit-border-before: 1px solid var(--cds-layer-hover); + border-block-start: 1px solid var(--cds-layer-hover); + color: var(--cds-text-primary,#161616); +} + +mark-down table { + margin-top: 1rem; + width: 100%; +} + +@media (min-width: 66rem) { + mark-down table { + max-width: 66.66%; + } +} + +mark-down table thead { + font-size: var(--cds-heading-compact-01-font-size,0.875rem); + font-weight: var(--cds-heading-compact-01-font-weight,600); + line-height: var(--cds-heading-compact-01-line-height,1.28572); + letter-spacing: var(--cds-heading-compact-01-letter-spacing,0.16px); + background-color: var(--cds-layer-accent); +} + +mark-down table tr { + border: none; + block-size: 3rem; + inline-size: 100%; +} + +mark-down table th { + background-color: var(--cds-layer-accent); + color: var(--cds-text-primary,#161616); + -webkit-padding-end: 1rem; + padding-inline-end: 1rem; + -webkit-padding-start: 1rem; + padding-inline-start: 1rem; +} + +mark-down table td, mark-down table th { + text-align: start; + vertical-align: middle; +} + +mark-down table tbody { + font-size: var(--cds-body-compact-01-font-size,0.875rem); + font-weight: var(--cds-body-compact-01-font-weight,400); + line-height: var(--cds-body-compact-01-line-height,1.28572); + letter-spacing: var(--cds-body-compact-01-letter-spacing,0.16px); + background-color: var(--cds-layer); + inline-size: 100%; +} + +mark-down table td, mark-down table tbody th { + background: var(--cds-layer); + -webkit-border-after: 1px solid var(--cds-border-subtle); + border-block-end: 1px solid var(--cds-border-subtle); + -webkit-border-before: 1px solid var(--cds-layer); + border-block-start: 1px solid var(--cds-layer); + color: var(--cds-text-secondary,#525252); + -webkit-padding-end: 1rem; + padding-inline-end: 1rem; + -webkit-padding-start: 1rem; + padding-inline-start: 1rem; +} \ No newline at end of file diff --git a/rule-server/src/static/archives/2024.08.29/doc/common/help.js b/rule-server/src/static/archives/2024.08.29/doc/common/help.js new file mode 100644 index 000000000..c8fa2f0ec --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/common/help.js @@ -0,0 +1,225 @@ +/****************************************************************************** + Copyright:: 2022- IBM, Inc + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ + +class HTMLBaseElement extends HTMLElement { + constructor(...args) { + const self = super(...args); + self.parsed = false; // guard to make it easy to do certain stuff only once + self.parentNodes = []; + return self; + } + + connectedCallback() { + // collect the parentNodes + let el = this; + while (el.parentNode) { + el = el.parentNode; + this.parentNodes.push(el); + } + // check if the parser has already passed the end tag of the component + // in which case this element, or one of its parents, should have a nextSibling + // if not (no whitespace at all between tags and no nextElementSiblings either) + // resort to DOMContentLoaded or load having triggered + if ([this, ...this.parentNodes].some((el) => el.nextSibling) || document.readyState !== "loading") { + if (this.childrenAvailableCallback) + this.childrenAvailableCallback(); + this.parsed = true; + } else { + this.mutationObserver = new MutationObserver(() => { + if ([this, ...this.parentNodes].some((el) => el.nextSibling) || document.readyState !== "loading") { + if (this.childrenAvailableCallback) + this.childrenAvailableCallback(); + this.parsed = true; + this.mutationObserver.disconnect(); + } + }); + + this.mutationObserver.observe(this, { + childList: true, + }); + } + } +} + +function isDarkMode() { + return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches); +} + +customElements.define( + "mark-down", + class extends HTMLBaseElement { + constructor() { + super(); + setTimeout(() => { + let converted = marked.parse(this.textContent); + this.innerHTML = converted + .replace(/<(\/?)ul>/g, "<$1bx-unordered-list>") + .replace(/<(\/?)li>/g, "<$1bx-list-item>") + .replace(/[ \r\n]*/g, "") + .replace(/<\/code>[ \r\n]*<\/pre>/g, ""); + }, 0) + } + // childrenAvailableCallback() { + // let converted = marked.parse(this.innerHTML); + // this.innerHTML = converted + // .replace(/<(\/?)ul>/g, "<$1bx-unordered-list>") + // .replace(/<(\/?)li>/g, "<$1bx-list-item>") + // .replace(/[ \r\n]*/g, "") + // .replace(/<\/code>[ \r\n]*<\/pre>/g, ""); + // } + } +); + +customElements.define( + "code-snippet", + class extends HTMLBaseElement { + childrenAvailableCallback() { + let oldCode = this.innerHTML; + this.innerHTML = ""; + // const shadowRoot = this.attachShadow({mode: 'open'}); + const shadowRoot = this; + let snip = document.createElement("bx-code-snippet"); + snip.setAttribute("type", "multi"); + snip.innerHTML = oldCode.replace(/ ruleInfo.msgArgs[matchedNum]); + document.querySelector("#ruleMessage").innerHTML = ruleMessage.replace(/&/g, "&").replace(//g, ">") + } + setTimeout(() => { + if (ruleInfo.snippet) { + let snip = ruleInfo.snippet; + snip = snip.replace(/( [a-zA-Z-]+="[^"]*")/g, "\n $1"); + let snipElem = document.createElement("code-snippet"); + for (let line of snip.split("\n")) { + snipElem.appendChild(document.createTextNode(line+"\n")); + } + let locSnippet = document.querySelector("#locSnippet"); + locSnippet.innerHTML = `

Element location

`; + locSnippet.appendChild(snipElem); + } + }, 0); + if (ruleInfo.value) { + let value = ruleInfo.value; + const val = valueMap[value[0]][value[1]]; + let icon = ""; + if (val === "Violation") icon = ``; + if (val === "Needs review") icon = ``; + if (val === "Recommendation") icon = ``; + let level = document.querySelector("#locLevel"); + let parent = level.parentElement; + level = parent.removeChild(level); + parent.insertBefore(level, parent.firstElementChild); + document.querySelector("#locLevel").innerHTML = `
${val}
`; + } + if (RULE_ID) { + document.querySelector("#ruleInfo").innerHTML = `

Rule ID: ${RULE_ID}${ruleInfo.reasonId ? `
Reason ID: ${ruleInfo.reasonId}

` : ""}`; + } + } +} + +if ("onhashchange" in window) {// does the browser support the hashchange event? + window.onhashchange = function () { + let ruleInfo = JSON.parse(decodeURIComponent(window.location.hash.substring(1))); + updateWithRuleInfo(ruleInfo); + } +} + +window.addEventListener("DOMContentLoaded", (evt) => { + let groupMsg = typeof RULE_MESSAGES !== "undefined" && (RULE_MESSAGES["en-US"].group || RULE_MESSAGES["en-US"][0]) || ""; + groupMsg = groupMsg.replace(/&/g, "&").replace(//g, ">"); + document.querySelector("#groupLabel").innerHTML = groupMsg; + let ruleInfo; + if (window.location.search && window.location.search.length > 0) { + const searchParams = new URLSearchParams(window.location.search); + ruleInfo = JSON.parse(decodeURIComponent(searchParams.get("issue"))); + } else if (window.location.hash && window.location.hash.length > 0) { + ruleInfo = JSON.parse(decodeURIComponent(window.location.hash.substring(1))); + } + updateWithRuleInfo(ruleInfo); + + if (isDarkMode()) { + document.body.setAttribute("class", "dds-theme-zone-g90"); + } else { + document.body.setAttribute("class", "dds-theme-zone-g10"); + } + +}) + diff --git a/rule-server/src/static/archives/2024.08.29/doc/common/rules.css b/rule-server/src/static/archives/2024.08.29/doc/common/rules.css new file mode 100644 index 000000000..515c8a230 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/common/rules.css @@ -0,0 +1,29 @@ +/****************************************************************************** + Copyright:: 2022- IBM, Inc + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +@import url('https://unpkg.com/carbon-components/css/carbon-components.min.css'); + +html, body, .toolHelp .bx--row:nth-child(2) { + height: 100%; +} + +body { + font-family: 'IBM Plex Sans', sans-serif; + padding: 1rem; +} + +h2 { + margin-top: 1rem; + font-size: 16px; + line-height: 24px; + font-weight: 600; +} diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/IBMA_Color_Contrast_WCAG2AA_PV.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/IBMA_Color_Contrast_WCAG2AA_PV.html new file mode 100644 index 000000000..70d9b1d64 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/IBMA_Color_Contrast_WCAG2AA_PV.html @@ -0,0 +1,90 @@ + + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/Rpt_Aria_ArticleRoleLabel_Implicit.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/Rpt_Aria_ArticleRoleLabel_Implicit.html new file mode 100644 index 000000000..283bed41c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/Rpt_Aria_ArticleRoleLabel_Implicit.html @@ -0,0 +1,95 @@ + + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/Rpt_Aria_GroupRoleLabel_Implicit.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/Rpt_Aria_GroupRoleLabel_Implicit.html new file mode 100644 index 000000000..d5cdca57e --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/Rpt_Aria_GroupRoleLabel_Implicit.html @@ -0,0 +1,107 @@ + + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/a_target_warning.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/a_target_warning.html new file mode 100644 index 000000000..667ca418e --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/a_target_warning.html @@ -0,0 +1,91 @@ + + + + a_target_warning - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/a_text_purpose.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/a_text_purpose.html new file mode 100644 index 000000000..2c7138526 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/a_text_purpose.html @@ -0,0 +1,108 @@ + + + + a_text_purpose - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/applet_alt_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/applet_alt_exists.html new file mode 100644 index 000000000..c8b9a1a00 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/applet_alt_exists.html @@ -0,0 +1,103 @@ + + + + applet_alt_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/application_content_accessible.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/application_content_accessible.html new file mode 100644 index 000000000..3eb9eeb14 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/application_content_accessible.html @@ -0,0 +1,97 @@ + + + + application_content_accessible - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/area_alt_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/area_alt_exists.html new file mode 100644 index 000000000..fad66e3df --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/area_alt_exists.html @@ -0,0 +1,101 @@ + + + + area_alt_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_accessiblename_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_accessiblename_exists.html new file mode 100644 index 000000000..7b6975aeb --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_accessiblename_exists.html @@ -0,0 +1,112 @@ + + + + aria_accessiblename_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_activedescendant_tabindex_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_activedescendant_tabindex_valid.html new file mode 100644 index 000000000..b73e726db --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_activedescendant_tabindex_valid.html @@ -0,0 +1,107 @@ + + + + aria_activedescendant_tabindex_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_activedescendant_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_activedescendant_valid.html new file mode 100644 index 000000000..0f3ad21b7 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_activedescendant_valid.html @@ -0,0 +1,103 @@ + + + + aria_activedescendant_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_application_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_application_label_unique.html new file mode 100644 index 000000000..74ce77ae0 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_application_label_unique.html @@ -0,0 +1,103 @@ + + + + aria_application_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_application_labelled.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_application_labelled.html new file mode 100644 index 000000000..b45966878 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_application_labelled.html @@ -0,0 +1,100 @@ + + + + aria_application_labelled - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_article_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_article_label_unique.html new file mode 100644 index 000000000..9a404e925 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_article_label_unique.html @@ -0,0 +1,104 @@ + + + + aria_article_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_allowed.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_allowed.html new file mode 100644 index 000000000..c144962bc --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_allowed.html @@ -0,0 +1,97 @@ + + + + aria_attribute_allowed - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_conflict.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_conflict.html new file mode 100644 index 000000000..de93cc132 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_conflict.html @@ -0,0 +1,109 @@ + + + + aria_attribute_conflict - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_deprecated.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_deprecated.html new file mode 100644 index 000000000..e0d6a25dd --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_deprecated.html @@ -0,0 +1,103 @@ + + + + aria_attribute_deprecated - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_exists.html new file mode 100644 index 000000000..6e3d8066d --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_exists.html @@ -0,0 +1,93 @@ + + + + aria_attribute_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_redundant.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_redundant.html new file mode 100644 index 000000000..04b98c64f --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_redundant.html @@ -0,0 +1,98 @@ + + + + aria_attribute_redundant - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_required.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_required.html new file mode 100644 index 000000000..a6368c79f --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_required.html @@ -0,0 +1,106 @@ + + + + aria_attribute_required - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_valid.html new file mode 100644 index 000000000..f3aeae30c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_valid.html @@ -0,0 +1,102 @@ + + + + aria_attribute_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + + + +
+
+
+ + \ No newline at end of file diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_value_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_value_valid.html new file mode 100644 index 000000000..15b357434 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_attribute_value_valid.html @@ -0,0 +1,94 @@ + + + + aria_attribute_value_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + \ No newline at end of file diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_banner_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_banner_label_unique.html new file mode 100644 index 000000000..ca98ec2f1 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_banner_label_unique.html @@ -0,0 +1,104 @@ + + + + aria_banner_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_banner_single.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_banner_single.html new file mode 100644 index 000000000..845247fa0 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_banner_single.html @@ -0,0 +1,98 @@ + + + + aria_banner_single - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_child_tabbable.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_child_tabbable.html new file mode 100644 index 000000000..4a030b145 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_child_tabbable.html @@ -0,0 +1,98 @@ + + + + aria_child_tabbable - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_child_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_child_valid.html new file mode 100644 index 000000000..8114ac69d --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_child_valid.html @@ -0,0 +1,121 @@ + + + + aria_child_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_label_unique.html new file mode 100644 index 000000000..ca8800820 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_label_unique.html @@ -0,0 +1,103 @@ + + + + aria_complementary_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_label_visible.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_label_visible.html new file mode 100644 index 000000000..34b03c6b5 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_label_visible.html @@ -0,0 +1,100 @@ + + + + aria_complementary_label_visible - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_labelled.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_labelled.html new file mode 100644 index 000000000..2dd634c90 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_complementary_labelled.html @@ -0,0 +1,100 @@ + + + + aria_complementary_labelled - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_content_in_landmark.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_content_in_landmark.html new file mode 100644 index 000000000..35c206de4 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_content_in_landmark.html @@ -0,0 +1,92 @@ + + + + aria_content_in_landmark - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_label_unique.html new file mode 100644 index 000000000..2b5641797 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_label_unique.html @@ -0,0 +1,104 @@ + + + + aria_contentinfo_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_misuse.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_misuse.html new file mode 100644 index 000000000..740efe106 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_misuse.html @@ -0,0 +1,105 @@ + + + + aria_contentinfo_misuse - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_single.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_single.html new file mode 100644 index 000000000..861de7861 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_contentinfo_single.html @@ -0,0 +1,100 @@ + + + + aria_contentinfo_single - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_descendant_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_descendant_valid.html new file mode 100644 index 000000000..e2154211c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_descendant_valid.html @@ -0,0 +1,101 @@ + + + + aria_descendant_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_document_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_document_label_unique.html new file mode 100644 index 000000000..9224ea9fc --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_document_label_unique.html @@ -0,0 +1,91 @@ + + + + aria_document_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_eventhandler_role_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_eventhandler_role_valid.html new file mode 100644 index 000000000..acdfcea1a --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_eventhandler_role_valid.html @@ -0,0 +1,92 @@ + + + + aria_eventhandler_role_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_form_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_form_label_unique.html new file mode 100644 index 000000000..ec58b65a1 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_form_label_unique.html @@ -0,0 +1,112 @@ + + + + aria_form_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_graphic_labelled.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_graphic_labelled.html new file mode 100644 index 000000000..d3d9b2125 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_graphic_labelled.html @@ -0,0 +1,99 @@ + + + + aria_graphic_labelled - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_hidden_nontabbable.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_hidden_nontabbable.html new file mode 100644 index 000000000..d7c54e671 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_hidden_nontabbable.html @@ -0,0 +1,113 @@ + + + + aria_hidden_nontabbable - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_id_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_id_unique.html new file mode 100644 index 000000000..b0bc3040c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_id_unique.html @@ -0,0 +1,98 @@ + + + + aria_id_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_img_labelled.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_img_labelled.html new file mode 100644 index 000000000..7dff4a079 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_img_labelled.html @@ -0,0 +1,100 @@ + + + + aria_img_labelled - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_keyboard_handler_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_keyboard_handler_exists.html new file mode 100644 index 000000000..6c840d10e --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_keyboard_handler_exists.html @@ -0,0 +1,103 @@ + + + + aria_keyboard_handler_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_landmark_name_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_landmark_name_unique.html new file mode 100644 index 000000000..556c2d184 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_landmark_name_unique.html @@ -0,0 +1,110 @@ + + + + aria_landmark_name_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_main_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_main_label_unique.html new file mode 100644 index 000000000..f063a76c8 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_main_label_unique.html @@ -0,0 +1,111 @@ + + + + aria_main_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_main_label_visible.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_main_label_visible.html new file mode 100644 index 000000000..bcdaf8ae9 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_main_label_visible.html @@ -0,0 +1,102 @@ + + + + aria_main_label_visible - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_navigation_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_navigation_label_unique.html new file mode 100644 index 000000000..ff7c4baa9 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_navigation_label_unique.html @@ -0,0 +1,106 @@ + + + + aria_navigation_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_parent_required.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_parent_required.html new file mode 100644 index 000000000..155570233 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_parent_required.html @@ -0,0 +1,98 @@ + + + + aria_parent_required - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_region_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_region_label_unique.html new file mode 100644 index 000000000..55466d5ef --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_region_label_unique.html @@ -0,0 +1,102 @@ + + + + aria_region_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_region_labelled.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_region_labelled.html new file mode 100644 index 000000000..082df90d9 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_region_labelled.html @@ -0,0 +1,102 @@ + + + + aria_region_labelled - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_allowed.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_allowed.html new file mode 100644 index 000000000..439e94700 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_allowed.html @@ -0,0 +1,105 @@ + + + + aria_role_allowed - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_redundant.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_redundant.html new file mode 100644 index 000000000..ab0dc4c50 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_redundant.html @@ -0,0 +1,107 @@ + + + + aria_role_redundant - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_valid.html new file mode 100644 index 000000000..896311194 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_role_valid.html @@ -0,0 +1,90 @@ + + + + aria_role_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_search_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_search_label_unique.html new file mode 100644 index 000000000..cea329abb --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_search_label_unique.html @@ -0,0 +1,100 @@ + + + + aria_search_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_toolbar_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_toolbar_label_unique.html new file mode 100644 index 000000000..4b1b4db28 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_toolbar_label_unique.html @@ -0,0 +1,102 @@ + + + + aria_toolbar_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_widget_labelled.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_widget_labelled.html new file mode 100644 index 000000000..52460feb5 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/aria_widget_labelled.html @@ -0,0 +1,102 @@ + + + + aria_widget_labelled - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/asciiart_alt_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/asciiart_alt_exists.html new file mode 100644 index 000000000..06a60bfa8 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/asciiart_alt_exists.html @@ -0,0 +1,91 @@ + + + + asciiart_alt_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/blink_css_review.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/blink_css_review.html new file mode 100644 index 000000000..801a20fca --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/blink_css_review.html @@ -0,0 +1,94 @@ + + + + blink_css_review - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/blink_elem_deprecated.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/blink_elem_deprecated.html new file mode 100644 index 000000000..e5ba6de0a --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/blink_elem_deprecated.html @@ -0,0 +1,94 @@ + + + + blink_elem_deprecated - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/blockquote_cite_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/blockquote_cite_exists.html new file mode 100644 index 000000000..0899d3948 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/blockquote_cite_exists.html @@ -0,0 +1,91 @@ + + + + blockquote_cite_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/canvas_content_described.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/canvas_content_described.html new file mode 100644 index 000000000..1f305d6e2 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/canvas_content_described.html @@ -0,0 +1,115 @@ + + + + canvas_content_described - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/caption_track_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/caption_track_exists.html new file mode 100644 index 000000000..45bdbbe4d --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/caption_track_exists.html @@ -0,0 +1,100 @@ + + + + caption_track_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_active_descendant.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_active_descendant.html new file mode 100644 index 000000000..d4d30b1bd --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_active_descendant.html @@ -0,0 +1,109 @@ + + + + combobox_active_descendant - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_autocomplete_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_autocomplete_valid.html new file mode 100644 index 000000000..0eeed4998 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_autocomplete_valid.html @@ -0,0 +1,136 @@ + + + + combobox_autocomplete_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_design_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_design_valid.html new file mode 100644 index 000000000..b9d827b06 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_design_valid.html @@ -0,0 +1,93 @@ + + + + combobox_design_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_focusable_elements.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_focusable_elements.html new file mode 100644 index 000000000..553320b99 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_focusable_elements.html @@ -0,0 +1,92 @@ + + + + combobox_focusable_elements - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_haspopup_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_haspopup_valid.html new file mode 100644 index 000000000..5069d1662 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_haspopup_valid.html @@ -0,0 +1,107 @@ + + + + combobox_haspopup_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_popup_reference.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_popup_reference.html new file mode 100644 index 000000000..d166b30a5 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/combobox_popup_reference.html @@ -0,0 +1,109 @@ + + + + combobox_popup_reference - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/dir_attribute_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/dir_attribute_valid.html new file mode 100644 index 000000000..443618ffc --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/dir_attribute_valid.html @@ -0,0 +1,89 @@ + + + + dir_attribute_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/download_keyboard_controllable.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/download_keyboard_controllable.html new file mode 100644 index 000000000..4bae1a219 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/download_keyboard_controllable.html @@ -0,0 +1,92 @@ + + + + download_keyboard_controllable - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/draggable_alternative_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/draggable_alternative_exists.html new file mode 100644 index 000000000..621e69815 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/draggable_alternative_exists.html @@ -0,0 +1,105 @@ + + + + draggable_alternative_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_accesskey_labelled.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_accesskey_labelled.html new file mode 100644 index 000000000..7cbc57d89 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_accesskey_labelled.html @@ -0,0 +1,97 @@ + + + + element_accesskey_labelled - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_accesskey_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_accesskey_unique.html new file mode 100644 index 000000000..2818e7745 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_accesskey_unique.html @@ -0,0 +1,100 @@ + + + + element_accesskey_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_attribute_deprecated.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_attribute_deprecated.html new file mode 100644 index 000000000..0136c1d56 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_attribute_deprecated.html @@ -0,0 +1,103 @@ + + + + element_attribute_deprecated - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_id_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_id_unique.html new file mode 100644 index 000000000..17580119f --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_id_unique.html @@ -0,0 +1,102 @@ + + + + element_id_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_lang_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_lang_valid.html new file mode 100644 index 000000000..bca07c8d9 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_lang_valid.html @@ -0,0 +1,108 @@ + + + + element_lang_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_mouseevent_keyboard.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_mouseevent_keyboard.html new file mode 100644 index 000000000..4b0fda7a8 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_mouseevent_keyboard.html @@ -0,0 +1,102 @@ + + + + element_mouseevent_keyboard - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_orientation_unlocked.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_orientation_unlocked.html new file mode 100644 index 000000000..d637b6c4c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_orientation_unlocked.html @@ -0,0 +1,112 @@ + + + + element_orientation_unlocked - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_scrollable_tabbable.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_scrollable_tabbable.html new file mode 100644 index 000000000..cf1c4069c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_scrollable_tabbable.html @@ -0,0 +1,115 @@ + + + + element_scrollable_tabbable - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_role_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_role_valid.html new file mode 100644 index 000000000..441bd42e4 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_role_valid.html @@ -0,0 +1,136 @@ + + + + element_tabbable_role_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_unobscured.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_unobscured.html new file mode 100644 index 000000000..1980fcbef --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_unobscured.html @@ -0,0 +1,103 @@ + + + + element_tabbable_unobscured - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_visible.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_visible.html new file mode 100644 index 000000000..e7a684f2f --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/element_tabbable_visible.html @@ -0,0 +1,124 @@ + + + + element_tabbable_visible - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/embed_alt_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/embed_alt_exists.html new file mode 100644 index 000000000..f6e037df5 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/embed_alt_exists.html @@ -0,0 +1,95 @@ + + + + embed_alt_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/embed_noembed_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/embed_noembed_exists.html new file mode 100644 index 000000000..a0aca36d8 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/embed_noembed_exists.html @@ -0,0 +1,102 @@ + + + + embed_noembed_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/emoticons_alt_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/emoticons_alt_exists.html new file mode 100644 index 000000000..2d06c83b0 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/emoticons_alt_exists.html @@ -0,0 +1,91 @@ + + + + emoticons_alt_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/error_message_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/error_message_exists.html new file mode 100644 index 000000000..1e1f3d5a2 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/error_message_exists.html @@ -0,0 +1,105 @@ + + + + error_message_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/fieldset_label_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/fieldset_label_valid.html new file mode 100644 index 000000000..50b49155c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/fieldset_label_valid.html @@ -0,0 +1,106 @@ + + + + fieldset_label_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/fieldset_legend_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/fieldset_legend_valid.html new file mode 100644 index 000000000..c68280bbb --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/fieldset_legend_valid.html @@ -0,0 +1,101 @@ + + + + fieldset_legend_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/figure_label_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/figure_label_exists.html new file mode 100644 index 000000000..35aceb565 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/figure_label_exists.html @@ -0,0 +1,104 @@ + + + + figure_label_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/form_font_color.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_font_color.html new file mode 100644 index 000000000..2818da309 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_font_color.html @@ -0,0 +1,90 @@ + + + + form_font_color - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/form_interaction_review.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_interaction_review.html new file mode 100644 index 000000000..30abfe2d6 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_interaction_review.html @@ -0,0 +1,92 @@ + + + + form_interaction_review - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/form_label_unique.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_label_unique.html new file mode 100644 index 000000000..d1b74b905 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_label_unique.html @@ -0,0 +1,90 @@ + + + + form_label_unique - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/form_submit_button_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_submit_button_exists.html new file mode 100644 index 000000000..509b44144 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_submit_button_exists.html @@ -0,0 +1,92 @@ + + + + form_submit_button_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/form_submit_review.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_submit_review.html new file mode 100644 index 000000000..6129ae2af --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/form_submit_review.html @@ -0,0 +1,93 @@ + + + + form_submit_review - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/frame_src_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/frame_src_valid.html new file mode 100644 index 000000000..bea8d0a99 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/frame_src_valid.html @@ -0,0 +1,95 @@ + + + + frame_src_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/frame_title_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/frame_title_exists.html new file mode 100644 index 000000000..5e0e81cbc --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/frame_title_exists.html @@ -0,0 +1,99 @@ + + + + frame_title_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/heading_content_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/heading_content_exists.html new file mode 100644 index 000000000..953e2d3d5 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/heading_content_exists.html @@ -0,0 +1,89 @@ + + + + heading_content_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/heading_markup_misuse.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/heading_markup_misuse.html new file mode 100644 index 000000000..1fa519ba4 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/heading_markup_misuse.html @@ -0,0 +1,92 @@ + + + + heading_markup_misuse - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/html_lang_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/html_lang_exists.html new file mode 100644 index 000000000..d66c20426 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/html_lang_exists.html @@ -0,0 +1,92 @@ + + + + html_lang_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/html_lang_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/html_lang_valid.html new file mode 100644 index 000000000..1d90f0a2a --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/html_lang_valid.html @@ -0,0 +1,111 @@ + + + + html_lang_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/html_skipnav_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/html_skipnav_exists.html new file mode 100644 index 000000000..97c0fbe6c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/html_skipnav_exists.html @@ -0,0 +1,91 @@ + + + + html_skipnav_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/iframe_interactive_tabbable.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/iframe_interactive_tabbable.html new file mode 100644 index 000000000..88576fd71 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/iframe_interactive_tabbable.html @@ -0,0 +1,105 @@ + + + + iframe_interactive_tabbable - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/imagebutton_alt_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/imagebutton_alt_exists.html new file mode 100644 index 000000000..6f3354129 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/imagebutton_alt_exists.html @@ -0,0 +1,90 @@ + + + + imagebutton_alt_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/imagemap_alt_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/imagemap_alt_exists.html new file mode 100644 index 000000000..2327fe32b --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/imagemap_alt_exists.html @@ -0,0 +1,101 @@ + + + + imagemap_alt_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_background.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_background.html new file mode 100644 index 000000000..501d5a5c6 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_background.html @@ -0,0 +1,90 @@ + + + + img_alt_background - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_decorative.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_decorative.html new file mode 100644 index 000000000..3f47082d2 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_decorative.html @@ -0,0 +1,93 @@ + + + + img_alt_decorative - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_misuse.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_misuse.html new file mode 100644 index 000000000..a15718c7d --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_misuse.html @@ -0,0 +1,91 @@ + + + + img_alt_misuse - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_null.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_null.html new file mode 100644 index 000000000..7aaa6538e --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_null.html @@ -0,0 +1,94 @@ + + + + img_alt_null - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_redundant.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_redundant.html new file mode 100644 index 000000000..e4adefc89 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_redundant.html @@ -0,0 +1,94 @@ + + + + img_alt_redundant - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_valid.html new file mode 100644 index 000000000..81d8347a7 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_alt_valid.html @@ -0,0 +1,99 @@ + + + + img_alt_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/img_ismap_misuse.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_ismap_misuse.html new file mode 100644 index 000000000..6ca9f2ca8 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_ismap_misuse.html @@ -0,0 +1,91 @@ + + + + img_ismap_misuse - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/img_longdesc_misuse.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_longdesc_misuse.html new file mode 100644 index 000000000..62d46371a --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/img_longdesc_misuse.html @@ -0,0 +1,98 @@ + + + + img_longdesc_misuse - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_autocomplete_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_autocomplete_valid.html new file mode 100644 index 000000000..07419cfb9 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_autocomplete_valid.html @@ -0,0 +1,121 @@ + + + + input_autocomplete_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_checkboxes_grouped.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_checkboxes_grouped.html new file mode 100644 index 000000000..f538de4eb --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_checkboxes_grouped.html @@ -0,0 +1,90 @@ + + + + input_checkboxes_grouped - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_fields_grouped.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_fields_grouped.html new file mode 100644 index 000000000..cdd42e7c8 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_fields_grouped.html @@ -0,0 +1,104 @@ + + + + input_fields_grouped - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_haspopup_conflict.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_haspopup_conflict.html new file mode 100644 index 000000000..3d0bb75f4 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_haspopup_conflict.html @@ -0,0 +1,120 @@ + + + + input_haspopup_conflict - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_after.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_after.html new file mode 100644 index 000000000..7aeaa1caf --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_after.html @@ -0,0 +1,98 @@ + + + + input_label_after - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_before.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_before.html new file mode 100644 index 000000000..f1e8b9ad7 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_before.html @@ -0,0 +1,99 @@ + + + + input_label_before - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_exists.html new file mode 100644 index 000000000..42ee41906 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_exists.html @@ -0,0 +1,94 @@ + + + + input_label_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_visible.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_visible.html new file mode 100644 index 000000000..db950076a --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_label_visible.html @@ -0,0 +1,127 @@ + + + + input_label_visible - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_onchange_review.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_onchange_review.html new file mode 100644 index 000000000..a9cae294b --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_onchange_review.html @@ -0,0 +1,103 @@ + + + + input_onchange_review - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/input_placeholder_label_visible.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_placeholder_label_visible.html new file mode 100644 index 000000000..a7d082dfc --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/input_placeholder_label_visible.html @@ -0,0 +1,107 @@ + + + + input_placeholder_label_visible - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/label_content_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/label_content_exists.html new file mode 100644 index 000000000..83638a423 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/label_content_exists.html @@ -0,0 +1,90 @@ + + + + label_content_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/label_name_visible.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/label_name_visible.html new file mode 100644 index 000000000..687551cb0 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/label_name_visible.html @@ -0,0 +1,97 @@ + + + + label_name_visible - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/label_ref_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/label_ref_valid.html new file mode 100644 index 000000000..7f240e323 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/label_ref_valid.html @@ -0,0 +1,97 @@ + + + + label_ref_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/list_children_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/list_children_valid.html new file mode 100644 index 000000000..2b7416267 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/list_children_valid.html @@ -0,0 +1,111 @@ + + + + list_children_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/list_markup_review.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/list_markup_review.html new file mode 100644 index 000000000..aef0e47c1 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/list_markup_review.html @@ -0,0 +1,91 @@ + + + + list_markup_review - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/list_structure_proper.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/list_structure_proper.html new file mode 100644 index 000000000..51825a449 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/list_structure_proper.html @@ -0,0 +1,89 @@ + + + + list_structure_proper - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/marquee_elem_avoid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/marquee_elem_avoid.html new file mode 100644 index 000000000..8ccae10d0 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/marquee_elem_avoid.html @@ -0,0 +1,94 @@ + + + + marquee_elem_avoid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/media_alt_brief.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_alt_brief.html new file mode 100644 index 000000000..efd7ae0f5 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_alt_brief.html @@ -0,0 +1,111 @@ + + + + media_alt_brief - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/media_alt_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_alt_exists.html new file mode 100644 index 000000000..71396386d --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_alt_exists.html @@ -0,0 +1,95 @@ + + + + media_alt_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/media_audio_transcribed.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_audio_transcribed.html new file mode 100644 index 000000000..d02377888 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_audio_transcribed.html @@ -0,0 +1,97 @@ + + + + media_audio_transcribed - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/media_autostart_controllable.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_autostart_controllable.html new file mode 100644 index 000000000..43c34071a --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_autostart_controllable.html @@ -0,0 +1,93 @@ + + + + media_autostart_controllable - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/media_keyboard_controllable.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_keyboard_controllable.html new file mode 100644 index 000000000..d5ec73e48 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_keyboard_controllable.html @@ -0,0 +1,111 @@ + + + + media_keyboard_controllable - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/media_live_captioned.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_live_captioned.html new file mode 100644 index 000000000..8f90d42c4 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_live_captioned.html @@ -0,0 +1,91 @@ + + + + media_live_captioned - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/media_track_available.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_track_available.html new file mode 100644 index 000000000..e89356c17 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/media_track_available.html @@ -0,0 +1,96 @@ + + + + media_track_available - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/meta_redirect_optional.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/meta_redirect_optional.html new file mode 100644 index 000000000..1aae651c5 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/meta_redirect_optional.html @@ -0,0 +1,94 @@ + + + + meta_redirect_optional - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/meta_refresh_delay.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/meta_refresh_delay.html new file mode 100644 index 000000000..14c3db809 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/meta_refresh_delay.html @@ -0,0 +1,95 @@ + + + + meta_refresh_delay - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/meta_viewport_zoomable.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/meta_viewport_zoomable.html new file mode 100644 index 000000000..665826d05 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/meta_viewport_zoomable.html @@ -0,0 +1,98 @@ + + + + meta_viewport_zoomable - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/noembed_content_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/noembed_content_exists.html new file mode 100644 index 000000000..c732e33d1 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/noembed_content_exists.html @@ -0,0 +1,100 @@ + + + + noembed_content_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/object_text_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/object_text_exists.html new file mode 100644 index 000000000..1e3b2571c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/object_text_exists.html @@ -0,0 +1,101 @@ + + + + object_text_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/page_title_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/page_title_exists.html new file mode 100644 index 000000000..2e97f758f --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/page_title_exists.html @@ -0,0 +1,103 @@ + + + + page_title_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/page_title_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/page_title_valid.html new file mode 100644 index 000000000..1007c9f80 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/page_title_valid.html @@ -0,0 +1,105 @@ + + + + page_title_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/script_focus_blur_review.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/script_focus_blur_review.html new file mode 100644 index 000000000..88f135481 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/script_focus_blur_review.html @@ -0,0 +1,96 @@ + + + + script_focus_blur_review - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/script_onclick_avoid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/script_onclick_avoid.html new file mode 100644 index 000000000..07132ad72 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/script_onclick_avoid.html @@ -0,0 +1,92 @@ + + + + script_onclick_avoid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/script_onclick_misuse.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/script_onclick_misuse.html new file mode 100644 index 000000000..e211e9d26 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/script_onclick_misuse.html @@ -0,0 +1,92 @@ + + + + script_onclick_misuse - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/script_select_review.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/script_select_review.html new file mode 100644 index 000000000..f4ce0fdec --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/script_select_review.html @@ -0,0 +1,97 @@ + + + + script_select_review - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/select_options_grouped.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/select_options_grouped.html new file mode 100644 index 000000000..255896592 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/select_options_grouped.html @@ -0,0 +1,90 @@ + + + + select_options_grouped - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/skip_main_described.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/skip_main_described.html new file mode 100644 index 000000000..a3674a81b --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/skip_main_described.html @@ -0,0 +1,100 @@ + + + + skip_main_described - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/skip_main_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/skip_main_exists.html new file mode 100644 index 000000000..aeff0fcd6 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/skip_main_exists.html @@ -0,0 +1,103 @@ + + + + skip_main_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/style_background_decorative.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_background_decorative.html new file mode 100644 index 000000000..6cf43d2e7 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_background_decorative.html @@ -0,0 +1,93 @@ + + + + style_background_decorative - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/style_before_after_review.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_before_after_review.html new file mode 100644 index 000000000..e83a2b1c0 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_before_after_review.html @@ -0,0 +1,95 @@ + + + + style_before_after_review - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/style_color_misuse.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_color_misuse.html new file mode 100644 index 000000000..e7906bfb2 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_color_misuse.html @@ -0,0 +1,89 @@ + + + + style_color_misuse - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/style_focus_visible.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_focus_visible.html new file mode 100644 index 000000000..fdc7d90e0 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_focus_visible.html @@ -0,0 +1,97 @@ + + + + style_focus_visible - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/style_highcontrast_visible.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_highcontrast_visible.html new file mode 100644 index 000000000..75e0e8a02 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_highcontrast_visible.html @@ -0,0 +1,100 @@ + + + + style_highcontrast_visible - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/style_hover_persistent.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_hover_persistent.html new file mode 100644 index 000000000..dc72cef43 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_hover_persistent.html @@ -0,0 +1,118 @@ + + + + style_hover_persistent - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/style_viewport_resizable.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_viewport_resizable.html new file mode 100644 index 000000000..b8daa7d29 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/style_viewport_resizable.html @@ -0,0 +1,93 @@ + + + + style_viewport_resizable - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/svg_graphics_labelled.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/svg_graphics_labelled.html new file mode 100644 index 000000000..785efcc07 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/svg_graphics_labelled.html @@ -0,0 +1,127 @@ + + + + svg_graphics_labelled - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_aria_descendants.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_aria_descendants.html new file mode 100644 index 000000000..4ec41910b --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_aria_descendants.html @@ -0,0 +1,110 @@ + + + + table_aria_descendants - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_caption_empty.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_caption_empty.html new file mode 100644 index 000000000..aa31cbc13 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_caption_empty.html @@ -0,0 +1,101 @@ + + + + table_caption_empty - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_caption_nested.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_caption_nested.html new file mode 100644 index 000000000..c52a43310 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_caption_nested.html @@ -0,0 +1,98 @@ + + + + table_caption_nested - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_exists.html new file mode 100644 index 000000000..fe05efe22 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_exists.html @@ -0,0 +1,93 @@ + + + + table_headers_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_ref_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_ref_valid.html new file mode 100644 index 000000000..15d66ea3d --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_ref_valid.html @@ -0,0 +1,91 @@ + + + + table_headers_ref_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_related.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_related.html new file mode 100644 index 000000000..addc41858 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_headers_related.html @@ -0,0 +1,91 @@ + + + + table_headers_related - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_layout_linearized.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_layout_linearized.html new file mode 100644 index 000000000..2e9a26134 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_layout_linearized.html @@ -0,0 +1,92 @@ + + + + table_layout_linearized - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_scope_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_scope_valid.html new file mode 100644 index 000000000..0632f7a4a --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_scope_valid.html @@ -0,0 +1,93 @@ + + + + table_scope_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_structure_misuse.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_structure_misuse.html new file mode 100644 index 000000000..2fe51c995 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_structure_misuse.html @@ -0,0 +1,91 @@ + + + + table_structure_misuse - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/table_summary_redundant.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_summary_redundant.html new file mode 100644 index 000000000..130448ab8 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/table_summary_redundant.html @@ -0,0 +1,101 @@ + + + + table_summary_redundant - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/target_spacing_sufficient.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/target_spacing_sufficient.html new file mode 100644 index 000000000..a18167c6a --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/target_spacing_sufficient.html @@ -0,0 +1,108 @@ + + + + target_spacing_sufficient - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/text_block_heading.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_block_heading.html new file mode 100644 index 000000000..dad93b0a2 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_block_heading.html @@ -0,0 +1,92 @@ + + + + text_block_heading - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/text_contrast_sufficient.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_contrast_sufficient.html new file mode 100644 index 000000000..6a1f68348 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_contrast_sufficient.html @@ -0,0 +1,92 @@ + + + + text_contrast_sufficient - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/text_quoted_correctly.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_quoted_correctly.html new file mode 100644 index 000000000..8daea810e --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_quoted_correctly.html @@ -0,0 +1,106 @@ + + + + text_quoted_correctly - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/text_sensory_misuse.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_sensory_misuse.html new file mode 100644 index 000000000..5886e86ac --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_sensory_misuse.html @@ -0,0 +1,96 @@ + + + + text_sensory_misuse - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/text_spacing_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_spacing_valid.html new file mode 100644 index 000000000..5b7b8fc45 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_spacing_valid.html @@ -0,0 +1,103 @@ + + + + text_spacing_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/text_whitespace_valid.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_whitespace_valid.html new file mode 100644 index 000000000..befb5cc2c --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/text_whitespace_valid.html @@ -0,0 +1,93 @@ + + + + text_whitespace_valid - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/widget_tabbable_exists.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/widget_tabbable_exists.html new file mode 100644 index 000000000..442e7f0ce --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/widget_tabbable_exists.html @@ -0,0 +1,98 @@ + + + + widget_tabbable_exists - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/en-US/widget_tabbable_single.html b/rule-server/src/static/archives/2024.08.29/doc/en-US/widget_tabbable_single.html new file mode 100644 index 000000000..002ba6652 --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/en-US/widget_tabbable_single.html @@ -0,0 +1,96 @@ + + + + widget_tabbable_single - Accessibility Checker Help + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/rule-server/src/static/archives/2024.08.29/doc/rules.html b/rule-server/src/static/archives/2024.08.29/doc/rules.html new file mode 100644 index 000000000..22e11d3ad --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/doc/rules.html @@ -0,0 +1,20112 @@ + + + Accessibility Checker Rules + + + + + + + + +
+ + IBM Accessibility 7.2IBM Accessibility 7.3WCAG 2.2 (A, AA)WCAG 2.1 (A, AA)WCAG 2.0 (A, AA) + +
+
+

1.1.1 Non-text Content [A]

+
All non-text content that is presented to the user has a text alternative that serves the equivalent purpose.
+ applet_alt_exists: <applet> elements must provide an 'alt' attribute and an alternative description + +  Violation — +
An <applet> element does not have an 'alt' attribute that provides a short text alternative Violation — + The 'alt' attribute value for an <applet> element duplicates the 'code' attribute Violation — + An <applet> element provides alternative text, but does not provide inner content + + img_alt_redundant: The text alternative for an image within a link should not repeat the link text or adjacent link text + +  Violation — + Link text is repeated in an image 'alt' value within the same link Violation — + Link text of previous link is repeated in image 'alt' value of a link Violation — + Image 'alt' value within a link is repeated in link text of the link after + + img_alt_valid: Images must have accessible names unless they are decorative or redundant + +  Violation — + Image 'alt' attribute value consists only of blank space(s) Violation — + The image has neither an accessible name nor is marked as decorative or redundant Violation — + The image does not have an 'alt' attribute or ARIA label, and the 'title' attribute value consists only of blank space(s) + + area_alt_exists: <area> elements in an image map must have a text alternative + +  Violation — + <area> element in an image map has no text alternative + + imagebutton_alt_exists: The <input> element of type "image" should have a text alternative + +  Violation — + The <input> element of type "image" has no text alternative + + imagemap_alt_exists: An image map and each <area> element in an image map must have text alternative(s) + +  Violation — + Image map or child <area> has no text alternative + + img_alt_decorative: Image designated as decorative must have 'alt="" + +  Violation — + Image designated as decorative has non-null 'alt' attribute + + img_alt_null: When the image 'alt' attribute is empty, the 'title' attribute must also be empty + +  Violation — + The image 'alt' attribute is empty, but the 'title' attribute is not empty + + object_text_exists: <object> element must have a text alternative for the content rendered by the object + +  Violation — + An <object> element does not have a text alternative + + svg_graphics_labelled: A none decorative SVG element must have an accessible name + +  Violation — + The SVG element has no accessible name + + application_content_accessible: Non-decorative static text and image content within an element with "application" role must be accessible + +  Needs review — + Verify that the non-decorative static text and image content within an element with "application" role are accessible + + img_alt_misuse: 'alt' attribute value must be a good inline replacement for the image + +  Needs review — + Verify that the file name serves as a good inline replacement for the image + + img_ismap_misuse: Server-side image map hot-spots must have duplicate text links + +  Needs review — + Server-side image map hot-spots do not have duplicate text links + + img_longdesc_misuse: The 'longdesc' attribute must reference HTML content + +  Needs review — + Verify that the file designated by the 'longdesc' attribute contains valid HTML content (file extension not recognized) + + media_alt_exists: Audio or video on the page must have a short text alternative that describes the media content + +  Needs review — + Filename used as label for embedded audio or video + + style_background_decorative: Images included by using CSS alone must not convey important information + +  Needs review — + Verify the CSS background image does not convey important information + + style_highcontrast_visible: Windows high contrast mode must be supported when using CSS to include, position or alter non-decorative content + +  Needs review — + Confirm Windows high contrast mode is supported when using CSS to include, position or alter non-decorative content + + figure_label_exists: A <figure> element must have an associated label + +  Recommendation — + The <figure> element does not have an associated label + + embed_alt_exists: Provide alternative content for <embed> elements + +  Recommendation — + Verify that the <embed> element has alternative content + + embed_noembed_exists: <embed> elements should be immediately followed by a non-embedded element + +  Recommendation — + Verify that the <embed> element is immediately followed by a non-embedded element + + media_alt_brief: Alternative text in 'alt' attribute should be brief (<150 characters) + +  Recommendation — + Text alternative is more than 150 characters + + noembed_content_exists: <noembed> elements should contain descriptive text + +  Recommendation — + Add descriptive text to the <noembed> element + + canvas_content_described: The <canvas> element may not be accessible + +  Recommendation — + Verify accessibility of the <canvas> element + + img_alt_background: Background images that convey important information must have a text alternative that describes the image + +  Recommendation — + Verify important background image information has a text alternative in system high contrast mode + + +
+

1.2.1 Audio-only and Video-only (Prerecorded) [A]

+
For prerecorded audio-only or video-only media, an alternative provides equivalent information.
+ media_audio_transcribed: Audio information should also be available in text form + +  Recommendation — + Provide transcripts for audio files + + +
+

1.2.2 Captions (Prerecorded) [A]

+
Captions are provided for all prerecorded audio content in synchronized media.
+ caption_track_exists: A <video> element must have a text alternative for any meaningful audio content + +  Needs review — + Verify that captions are available for any meaningful audio or provide a caption track for the <video> element + + +
+

1.2.3 Audio Description or Media Alternative (Prerecorded) [A]

+
An alternative for time-based media or audio description of the prerecorded video content is provided for synchronized media.
+ media_track_available: Pre-recorded media should have an audio track that describes visual information + +  Recommendation — + Verify availability of a user-selectable audio track with description of visual content + + +
+

1.2.4 Captions (Live) [AA]

+
Captions are provided for all live audio content in synchronized media.
+ media_live_captioned: Live media (streaming video with audio) should have captions for audio content + +  Recommendation — + Verify captions are provided for live media (streaming video with audio) + + +
+

1.2.5 Audio Description (Prerecorded) [AA]

+
Audio description is provided for all prerecorded video content in synchronized media.
+ media_track_available: Pre-recorded media should have an audio track that describes visual information + +  Recommendation — + Verify availability of a user-selectable audio track with description of visual content + + +
+

1.3.1 Info and Relationships [A]

+
Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text.
+ input_checkboxes_grouped: Related sets of radio buttons or checkboxes should be programmatically grouped + +  Violation — + {0} input found that has the same name, "{2}" as a {1} input Violation — + {0} input is not in the group with another {0} with the name "{1}" Violation — + {0} input and others with the name "{1}" are not grouped together Violation — + {0} input is in a different group than another {0} with the name "{1}" Needs review — + Verify that this ungrouped checkbox input is not related to other checkboxes Needs review — + Verify that this un-named, ungrouped checkbox input is not related to other checkboxes + + table_headers_ref_valid: The 'headers' attribute should refer to a valid cell in the same table + +  Violation — + The 'headers' attribute value "{0}" does not reference a valid 'id' in this document Violation — + The 'headers' attribute value "{0}" refers to itself Violation — + The 'headers' attribute value "{0}" does not refer to a cell in the same table Violation — + The 'headers' attribute value "{0}" does not refer to a cell indicated with <th> or a role of "columnheader" or "rowheader" + + fieldset_label_valid: Groups with nested inputs must have unique accessible name + +  Violation — + Group/Fieldset does not have an accessible name Violation — + Group/Fieldset "{0}" has a duplicate name to another group + + table_scope_valid: Value for 'scope' attribute must be "row", "col", "rowgroup", or "colgroup" + +  Violation — + Value provided is invalid for the 'scope' attribute Violation — + The 'scope' attribute should only be used on a <th> element + + aria_hidden_nontabbable: A hidden element should not contain any tabbable elements + +  Violation — + Element "{0}" should not be focusable within the subtree of an element with an 'aria-hidden' attribute with value 'true' + + aria_parent_required: Each element with an implicit or explicit role must be contained within a valid element + +  Violation — + Element with "{0}" role is not contained in or owned by an element with one of the following roles: "{1}" + + form_label_unique: Form controls should have exactly one label + +  Violation — + Form control has more than one label + + label_ref_valid: The 'for' attribute for a label must reference a non-empty, unique 'id' attribute of an <input> element + +  Violation — + The value "{0}" of the 'for' attribute is not the 'id' of a valid <input> element + + table_caption_empty: A <caption> element for a <table> element must contain descriptive text + +  Violation — + The <table> element has an empty <caption> element + + table_caption_nested: The <caption> element must be nested inside the associated <table> element + +  Violation — + <caption> element is not nested inside a <table> element + + table_headers_exists: Data table must identify headers + +  Violation — + Table has no headers identified + + table_headers_related: For a complex data table, all <th> and <td> elements must be related via 'header' or 'scope' attributes + +  Violation — + Complex table does not have headers for each cell properly defined with 'header' or 'scope' + + table_structure_misuse: Table elements with 'role="presentation" or 'role="none" should not have structural elements or attributes + +  Violation — + The <{0}> element with "presentation" role or "none" role has structural element(s) and/or attribute(s) '{1}' + + table_summary_redundant: The table summary must not duplicate the caption + +  Violation — + The table summary duplicates the caption + + blockquote_cite_exists: Use <blockquote> only for quotations, not indentation + +  Needs review — + Verify that <blockquote> should have a 'cite' attribute and not be used for indentation only + + heading_markup_misuse: Heading elements must not be used for presentation + +  Needs review — + Verify that the heading element is a genuine heading + + list_markup_review: Proper HTML elements should be used to create a list + +  Needs review — + Verify this is a list and if so, modify to use proper HTML elements for the list + + text_block_heading: Heading text should use a heading element or role + +  Needs review — + Confirm this text '{0}' is used as a heading and if so, modify to use a heading element or role + + text_quoted_correctly: Quotations should be marked with <q> or <blockquote> elements + +  Needs review — + If the following text is a quotation, mark it as a <q> or <blockquote> element: {0} + + fieldset_legend_valid: <fieldset> elements should have a single, non-empty <legend> as a label + +  Recommendation — + <fieldset> element does not have a <legend> Recommendation — + <fieldset> element has more than one <legend> Recommendation — + <fieldset> element <legend> is empty + + aria_child_valid: An element with an ARIA role must own a required child + +  Recommendation — + The element with role "{0}" does not own any child element with any of the following role(s): "{1}" Recommendation — + The element with role "{0}" owns the child element with the role "{1}" that is not one of the allowed role(s): "{2}" + + input_fields_grouped: Groups of logically related input elements should be contained within a <fieldset> element + +  Recommendation — + Use the <fieldset> element to group logically related input elements + + list_structure_proper: List elements should only be used for lists of related items + +  Recommendation — + List element is missing or improperly structured + + select_options_grouped: Groups of related options within a selection list should be grouped with <optgroup> + +  Recommendation — + Group of related options may need <optgroup> + + table_layout_linearized: Avoid using tables to format text documents in columns unless the table can be linearized + +  Recommendation — + Verify table is not being used to format text content in columns unless the table can be linearized + + +
+

1.3.2 Meaningful Sequence [A]

+
When the sequence in which content is presented affects its meaning, a correct reading sequence can be programmatically determined.
+ dir_attribute_valid: 'dir' attribute value must be "ltr", "rtl", or "auto" + +  Violation — + Invalid value used for the 'dir' attribute + + text_whitespace_valid: Space characters should not be used to control spacing within a word + +  Needs review — + Space characters should not be used to create space between the letters of a word + + style_highcontrast_visible: Windows high contrast mode must be supported when using CSS to include, position or alter non-decorative content + +  Needs review — + Confirm Windows high contrast mode is supported when using CSS to include, position or alter non-decorative content + + +
+

1.3.3 Sensory Characteristics [A]

+
Instructions provided for understanding and operating content do not rely solely on sensory characteristics of components such as shape, size, visual location, orientation, or sound.
+ text_sensory_misuse: Instructions should be meaningful without relying solely on shape, size, or location words + +  Needs review — + Confirm the word(s) '{0}' of the user instruction is used to indicate a logical rather than visual position Needs review — + Confirm the user instruction is still understandable without the word(s) '{0}' + + +
+

1.3.4 Orientation [AA]

+
Content does not restrict its view and operation to a single display orientation, such as portrait or landscape.
+ element_orientation_unlocked: Elements should not be restricted to either landscape or portrait orientation using CSS transform property + +  Violation — + The element <{0}> is restricted to either landscape or portrait orientation using CSS transform property + + +
+

1.3.5 Identify Input Purpose [AA]

+
The purpose of each input field that collects information about the user can be programmatically determined when the field serves a common purpose.
+ input_autocomplete_valid: The 'autocomplete' attribute's token(s) must be appropriate for the input form field + +  Violation — + The 'autocomplete' attribute's token(s) are not appropriate for the input form field Violation — + The 'autocomplete' attribute's token(s) are not appropriate for an input form field of any type Violation — + The 'autocomplete' attribute has an incorrect value + + +
+

1.4.1 Use of Color [A]

+
Color is not used as the only visual means of conveying information, indicating an action, prompting a response, or distinguishing a visual element.
+ form_font_color: Combine color and descriptive markup to indicate required form fields + +  Needs review — + Check color is not used as the only visual means to convey which fields are required + + style_color_misuse: Combine color and descriptive markup to convey information + +  Needs review — + Verify color is not used as the only visual means of conveying information + + +
+

1.4.2 Audio Control [A]

+
If any audio plays automatically for more than 3 seconds, either a mechanism is available to pause or stop the audio, or a mechanism is available to control audio volume independently from the overall system volume level.
+ media_autostart_controllable: Mechanism must be available to pause or stop and control the volume of the audio that plays automatically + +  Needs review — + Verify there is a mechanism to pause or stop and control the volume for the audio that plays automatically + + +
+

1.4.3 Contrast (Minimum) [AA]

+
The visual presentation of text and images of text has a contrast ratio of at least 4.5:1, with a 3:1 ratio for large-scale text.
+ text_contrast_sufficient: The contrast ratio of text with its background must meet WCAG AA requirements + +  Violation — + Text contrast of {0} with its background is less than the WCAG AA minimum requirements for text of size {1}px and weight of {2} Needs review — + The foreground text and its background color are both detected as {3}. Verify the text meets the WCAG AA requirements for minimum contrast Needs review — + Verify the contrast ratio of the text against the lightest and the darkest colors of the background meets the WCAG AA minimum requirements for text of size {1}px and weight of {2} Needs review — + Verify the contrast ratio of the text with shadow meets the WCAG AA minimum requirements for text of size {1}px and weight of {2} + + +
+

1.4.4 Resize text [AA]

+
Text can be resized without assistive technology up to 200 percent without loss of content or functionality.
+ style_viewport_resizable: Text must scale up to 200% without loss of content or functionality + +  Needs review — + Verify that text sized using viewport units can be resized up to 200% + + meta_viewport_zoomable: The 'meta[name=viewport]' should not prevent the browser zooming the content + +  Recommendation — + Confirm the 'meta[name=viewport]' with "{0}" can be zoomed by user + + +
+

1.4.5 Images of Text [AA]

+
If the technologies being used can achieve the visual presentation, text should not be used to convey information rather than images of text.
+ +
+

1.4.10 Reflow [AA]

+
Content can reflow without loss of information or functionality, and without requiring scrolling in two dimensions.
+ style_viewport_resizable: Text must scale up to 200% without loss of content or functionality + +  Needs review — + Verify that text sized using viewport units can be resized up to 200% + + +
+

1.4.11 Non-text Contrast [AA]

+
The parts of graphical objects required to understand the content, and the visual information required to identify UI components and states, have a contrast ratio of at least 3:1 against adjacent colors.
+ style_highcontrast_visible: Windows high contrast mode must be supported when using CSS to include, position or alter non-decorative content + +  Needs review — + Confirm Windows high contrast mode is supported when using CSS to include, position or alter non-decorative content + + +
+

1.4.12 Text Spacing [AA]

+
No loss of content or functionality occurs when users change letter, word and paragraph spacing, as well as line height.
+ text_spacing_valid: CSS !important should not be used in inline style to control letter or word spacing or line height + +  Violation — + CSS !important should not be used in inline ‘letter-spacing’ style Violation — + CSS !important should not be used in inline ‘word-spacing’ style Violation — + CSS !important should not be used in inline ‘line-height’ style + + +
+

1.4.13 Content on Hover or Focus [AA]

+
Where hover or focus actions cause additional content to become visible and hidden, the additional content is dismissable, hoverable and persistent.
+ style_hover_persistent: The pointer should be able to move over content displayed on hover + +  Needs review — + Confirm the pointer can be positioned over the displayed element, not just the trigger Needs review — + Confirm the pointer can be positioned over all the information displayed on hover Needs review — + Confirm the margin style attribute has not prevented the pointer from hovering over the displayed element, not just the trigger + + +
+

2.1.1 Keyboard [A]

+
All functionality of the content is operable through a keyboard interface without requiring specific timings for individual keystrokes.
+ aria_activedescendant_tabindex_valid: Element using 'aria-activedescendant' property should be tabbable + +  Violation — + The <{0}> element using 'aria-activedescendant' set to "{1}" is not tabbable + + aria_child_tabbable: UI component must have at least one tabbable descendant for keyboard access + +  Violation — + None of the descendent elements with "{1}" role is tabbable + + element_scrollable_tabbable: Scrollable elements should be tabbable or contain tabbable content + +  Violation — + The scrollable element <{0}> with non-interactive content is not tabbable + + iframe_interactive_tabbable: Iframe with interactive content should not be excluded from tab order using tabindex + +  Violation — + The <iframe> with interactive content is excluded from tab order using tabindex + + application_content_accessible: Non-decorative static text and image content within an element with "application" role must be accessible + +  Needs review — + Verify that the non-decorative static text and image content within an element with "application" role are accessible + + aria_keyboard_handler_exists: Interactive WAI_ARIA UI components must provide keyboard access + +  Needs review — + Verify the <{0}> element with "{1}" role has keyboard access + + script_focus_blur_review: Scripting must not remove focus from content that normally receives focus + +  Needs review — + Verify script does not remove focus from content that normally receives focus + + script_onclick_misuse: Scripts should not be used to emulate links + +  Needs review — + Possible use of a script to emulate a link + + widget_tabbable_exists: Component must have at least one tabbable element + +  Needs review — + Component with "{0}" role does not have a tabbable element + + widget_tabbable_single: Components with a widget role must have no more than one tabbable element + +  Needs review — + Component with "{0}" role has more than one tabbable element + + media_keyboard_controllable: Media using <audio> and/or <video> elements must have keyboard accessible controls + +  Needs review — + Verify media using <audio> and/or <video> elements have keyboard accessible controls + + script_onclick_avoid: Scripts should not be used to emulate links + +  Recommendation — + Verify that 'onclick' events are not used in script to emulate a link + + canvas_content_described: The <canvas> element may not be accessible + +  Recommendation — + Verify accessibility of the <canvas> element + + element_mouseevent_keyboard: All interactive content with mouse event handlers must have equivalent keyboard access + +  Recommendation — + Confirm the <{0}> element with mouse event handler(s) '{1}' has a corresponding keyboard handler(s) + + +
+

2.1.2 No Keyboard Trap [A]

+
If keyboard focus can be moved to a component using a keyboard interface, then focus can be moved away from that component using only a keyboard interface, and, if it requires more than unmodified arrow or tab keys or other standard exit methods, the user is advised of the method for moving focus away.
+ download_keyboard_controllable: File download mechanisms should be keyboard-operable and preserve page focus location + +  Recommendation — + Verify that the file download mechanism does not cause a keyboard trap + + +
+

2.1.4 Character Key Shortcuts [A]

+
If a keyboard shortcut is implemented using only letter, punctuation, number or symbol characters, then the shortcut can be turned off, remapped or activated only on focus.
+ +
+

2.2.1 Timing Adjustable [A]

+
For each time limit that is set by the content, the user can turn off, adjust, or extend the limit.
+ meta_redirect_optional: Page should not automatically refresh without warning or option to turn it off or adjust the time limit + +  Violation — + Check page does not automatically refresh without warning or options Violation — + Check page does not automatically refresh without warning or options + + meta_refresh_delay: Pages should not refresh automatically + +  Needs review — + Verify page is not being caused to refresh automatically + + +
+

2.2.2 Pause, Stop, Hide [A]

+
For moving, blinking, scrolling, or auto-updating information, the user can pause, stop, hide or adjust the information.
+ blink_elem_deprecated: Content that blinks persistently must not be used + +  Violation — + Content found that blinks persistently + + marquee_elem_avoid: The <marquee> element is obsolete and should not be used + +  Violation — + Scrolling content found that uses the obsolete <marquee> element + + blink_css_review: Do not use the "blink" value of the 'text-decoration' property for longer than five seconds + +  Needs review — + Check the "blink" value of the CSS 'text-decoration' property is not used for more than than five seconds + + +
+

2.3.1 Three Flashes or Below Threshold [A]

+
Content does not contain anything that flashes more than three times in any one second period, or the flash is below the general flash and red flash thresholds.
+ +
+

2.4.1 Bypass Blocks [A]

+
A mechanism is available to bypass blocks of content that are repeated on multiple Web pages.
+ aria_application_label_unique: Each element with "application" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "application" role do not have unique labels + + aria_application_labelled: Each element with "application" role must have a label that describes its purpose + +  Violation — + Element with "application" role does not have a label + + aria_article_label_unique: Each element with "article" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "article" role do not have unique labels + + aria_banner_label_unique: Each element with "banner" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "banner" role do not have unique labels + + aria_banner_single: A page, document, or application should only have one element with "banner" role + +  Violation — + Multiple elements with "banner" role found on the page + + aria_complementary_label_unique: Each element with "complementary" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "complementary" role do not have unique labels + + aria_complementary_labelled: Each element with "complementary" role must have a label that describes its purpose + +  Violation — + Element with "complementary" role does not have a label + + aria_content_in_landmark: All content must reside within an element with a landmark role + +  Violation — + Content is not within a landmark element + + aria_contentinfo_label_unique: Each element with "contentinfo" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "contentinfo" role do not have unique labels + + aria_contentinfo_single: A page, document, or application should only have one element with "contentinfo" role + +  Violation — + Multiple elements with "contentinfo" role found on the page + + aria_document_label_unique: Each element with "document" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "document" roles do not have unique labels + + aria_form_label_unique: Each element with "form" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "form" role do not have unique labels + + aria_landmark_name_unique: Each landmark should have a unique 'aria-labelledby' or 'aria-label' or be nested in a different parent region + +  Violation — + Multiple elements with "{0}" landmarks within the same parent region are not distinguished from one another because they have the same "{1}" label + + aria_main_label_unique: Each element with "main" role must have unique label that describes its purposes + +  Violation — + Multiple elements with "main" role do not have unique labels + + aria_navigation_label_unique: Each element with "navigation" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "navigation" role do not have unique labels + + aria_region_label_unique: Each element with "region" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "region" role do not have unique labels + + aria_region_labelled: Each element with "region" role must have a label that describes its purpose + +  Violation — + Element with "region" role does not have a label + + aria_search_label_unique: Each element with "search" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "search" role do not have unique labels + + aria_toolbar_label_unique: Each element with "toolbar" role must have a unique label that describes its purpose + +  Violation — + Multiple elements with "toolbar" roles do not have unique labels + + skip_main_exists: Pages must provide a way to skip directly to the main content + +  Violation — + The page does not provide a way to quickly navigate to the main content (ARIA "main" landmark or a skip link) + + frame_src_valid: A <frame> containing non-HTML content must be made accessible + +  Needs review — + Verify <frame> content is accessible + + html_skipnav_exists: Provide a way to bypass blocks of content that are repeated on multiple Web pages + +  Needs review — + Verify there is a way to bypass blocks of content that are repeated on multiple Web pages + + skip_main_described: The description of a hyperlink used to skip content must communicate where it links to + +  Needs review — + Verify that if this hyperlink skips content, the description communicates where it links to + + aria_complementary_label_visible: Each element with "complementary" role should have a visible label that describes its purpose + +  Recommendation — + Element with "complementary" role does not have a visible label + + aria_contentinfo_misuse: Each element with "contentinfo" role is only permitted with an element with "main" role + +  Recommendation — + Element with "contentinfo" role is present without an element with "main" role + + aria_main_label_visible: Each element with "main" role should have a unique visible label that describes its purpose + +  Recommendation — + Multiple elements with "main" role do not have unique visible labels + + +
+

2.4.2 Page Titled [A]

+
Web pages, non-web documents, and software have titles that describe topic or purpose.
+ page_title_exists: The page should have a title that correctly identifies the subject of the page + +  Violation — + Missing <head> element so there can be no <title> element present Violation — + Missing <title> element in <head> element Violation — + The <title> element is empty (no innerHTML) + + page_title_valid: Page <title> should be a descriptive title, rather than a filename + +  Needs review — + Verify that using the filename as the page <title> value is descriptive + + +
+

2.4.3 Focus Order [A]

+
If content can be navigated sequentially and the navigation sequences affect meaning or operation, focusable components receive focus in an order that preserves meaning and operability.
+ widget_tabbable_single: Components with a widget role must have no more than one tabbable element + +  Needs review — + Component with "{0}" role has more than one tabbable element + + +
+

2.4.4 Link Purpose (In Context) [A]

+
The purpose of each link can be determined from the link text alone or from the link text together with its programmatically determined link content.
+ img_alt_redundant: The text alternative for an image within a link should not repeat the link text or adjacent link text + +  Violation — + Link text is repeated in an image 'alt' value within the same link Violation — + Link text of previous link is repeated in image 'alt' value of a link Violation — + Image 'alt' value within a link is repeated in link text of the link after + + a_text_purpose: Hyperlinks must have an accessible name for their purpose + +  Violation — + Hyperlink has no link text, label or image with a text alternative + + +
+

2.4.5 Multiple Ways [AA]

+
More than one way is available to locate a Web page within a set of Web pages, except where the Web Page is the result of, or a step in, a process.
+ +
+

2.4.6 Headings and Labels [AA]

+
Headings and labels describe topic or purpose.
+ heading_content_exists: Heading elements must provide descriptive text + +  Recommendation — + Heading element has no descriptive content + + +
+

2.4.7 Focus Visible [AA]

+
Any keyboard operable user interface has a mode of operation where the keyboard focus indicator is visible.
+ element_tabbable_visible: A tabbable element should be visible on the screen when it has keyboard focus + +  Needs review — + Confirm the element should be tabbable and if so, it becomes visible when it has keyboard focus + + script_focus_blur_review: Scripting must not remove focus from content that normally receives focus + +  Needs review — + Verify script does not remove focus from content that normally receives focus + + style_focus_visible: The keyboard focus indicator should be visible when default border or outline is modified by CSS + +  Needs review — + Check the keyboard focus indicator is visible when using CSS declaration for 'border' or 'outline' + + +
+

2.4.11 Focus Not Obscured (Minimum) [AA]

+
When an element receives focus, it is not entirely covered by other content.
+ +
+

2.5.1 Pointer Gestures [A]

+
All functionality that uses multipoint or path-based gestures for operation can be operated with a single pointer without a path-based gesture.
+ +
+

2.5.2 Pointer Cancellation [A]

+
For functionality that can be operated using a single pointer, completion of the function is on the up-event with an ability to abort, undo or reverse the outcome.
+ +
+

2.5.3 Label in Name [A]

+
For user interface components with labels that include text or images of text, the accessible name contains the text that is presented visually.
+ label_name_visible: Accessible name must match or contain the visible label text + +  Violation — + Accessible name does not match or contain the visible label text + + input_label_visible: An input element must have an associated visible label + +  Needs review — + The ‘placeholder’ is the only visible label Needs review — + The input element does not have an associated visible label + + +
+

2.5.4 Motion Actuation [A]

+
Functionality that can be operated by motion can also be operated by user interface components, and the motion trigger can be disabled.
+ +
+

2.5.7 Dragging Movement [AA]

+
All functionality that uses a dragging movement for operation can be achieved by a single pointer without dragging.
+ +
+

2.5.8 Minimum Target Size [AA]

+
The size of the target for pointer inputs is at least 24 by 24 CSS pixels.
+ +
+

3.1.1 Language of Page [A]

+
The default human language of Web pages, non-Web documents, or software can be programmatically determined.
+ html_lang_exists: Page must identify the default language of the document with a 'lang' attribute + +  Violation — + Page detected as XHTML 1.0, but has neither 'lang' nor 'xml:lang' attributes Violation — + Page detected as XHTML, but does not have an 'xml:lang' attribute Violation — + Page detected as HTML, but does not have a 'lang' attribute Violation — + Page detected with 'lang' and 'xml:lang' attributes and primary languages do not match: "{0}", "{1}" Violation — + Page detected with 'lang' and 'xml:lang' attributes that do not match: "{0}", "{1}" Needs review — + Page detected as XHTML 1.0 with only a 'lang' attribute. Confirm that page is only delivered via text/html mime type Needs review — + Page detected as XHTML 1.0 with only an 'xml:lang' attribute. Confirm that page is only delivered via xml mime type + + html_lang_valid: The default human language of the page must be valid and specified in accordance with BCP 47 + +  Violation — + Specified 'lang' attribute does not include a valid primary language Violation — + Specified 'lang' attribute does not conform to BCP 47 Violation — + Specified 'xml:lang' attribute does not include a valid primary language Violation — + Specified 'xml:lang' attribute does not conform to BCP 47 + + +
+

3.1.2 Language of Parts [AA]

+
The human language of each passage or phrase in the content can be programmatically determined.
+ element_lang_valid: The change in language of specific content must be valid and specified in accordance with BCP 47 + +  Violation — + Specified 'lang' attribute does not include a valid primary language Violation — + Specified 'lang' attribute does not conform to BCP 47 Violation — + Specified 'xml:lang' attribute does not include a valid primary language Violation — + Specified 'xml:lang' attribute does not conform to BCP 47 + + +
+

3.2.1 On Focus [A]

+
When any component receives focus, it does not initiate a change of context.
+ script_focus_blur_review: Scripting must not remove focus from content that normally receives focus + +  Needs review — + Verify script does not remove focus from content that normally receives focus + + script_select_review: No changes of context should occur when a selection value receives focus + +  Needs review — + Verify that no change of context or action occurs when selection options in this component receive focus + + +
+

3.2.2 On Input [A]

+
Changing the setting of any user interface component does not automatically cause a change of context unless the user has been advised of the behavior before using the component.
+ form_interaction_review: User should be informed in advance when interacting with content causes a change of context + +  Needs review — + Verify that interacting with content will not open pop-up windows or change the active window without informing the user + + form_submit_button_exists: A <form> element should have a submit button or an image button + +  Needs review — + Verify the <form> element has a submit button or an image button + + input_onchange_review: Users must be advised if, due to a change of element value, a form automatically submits, a new window opens, or a change in focus occurs + +  Needs review — + Confirm that the user is advised if, due to a change of element value, a form automatically submits, a new window opens, or a change in focus occurs + + a_target_warning: Users should be warned in advance if their input action will open a new window + +  Recommendation — + Inform the user when their input action will open a new window + + +
+

3.2.3 Consistent Navigation [AA]

+
Navigational mechanisms that are repeated on multiple Web pages within a set of Web pages occur in the same relative order each time they are repeated, unless a change is initiated by the user.
+ +
+

3.2.4 Consistent Identification [AA]

+
Components that have the same functionality within a set of Web pages are identified consistently.
+ +
+

3.2.6 Consistent Help [AA]

+
Make it easier to find help and support. If a Web page contains help mechanisms they occur in the same order relative to other page content, unless a change is initiated by the user.
+ +
+

3.3.1 Error Identification [A]

+
If an input error is automatically detected, the item that is in error is identified and the error is described to the user in text.
+ error_message_exists: A custom error message must reference a valid 'id' value and when triggered the message must be appropriately exposed + +  Violation — + Custom error message has invalid reference 'id' value Violation — + Custom error message is not visible + + +
+

3.3.2 Labels or Instructions [A]

+
Labels or instructions are provided when content requires user input.
+ fieldset_label_valid: Groups with nested inputs must have unique accessible name + +  Violation — + Group/Fieldset does not have an accessible name Violation — + Group/Fieldset "{0}" has a duplicate name to another group + + input_label_after: Checkboxes and radio buttons must have a label after the input control + +  Violation — + Checkbox or radio button is nested in label, so label is not after the input control Violation — + Label text is located before its associated checkbox or radio button element + + input_label_before: Text inputs and <select> elements must have a label before the input control + +  Violation — + Text input is nested in label such that input precedes the label text Violation — + Label text is located after its associated text input or <select> element + + input_label_visible: An input element must have an associated visible label + +  Needs review — + The ‘placeholder’ is the only visible label Needs review — + The input element does not have an associated visible label + + element_accesskey_labelled: An element with an assigned 'accesskey' attribute must have an associated label + +  Recommendation — + The element with an assigned 'accesskey' attribute does not have an associated label + + +
+

3.3.3 Error Suggestion [AA]

+
If an input error is automatically detected and suggestions for correction are known, then the suggestions are provided to the user, unless it would jeopardize the security or purpose of the content.
+ +
+

3.3.4 Error Prevention (Legal, Financial, Data) [AA]

+
For content that cause legal commitments or financial transactions for the user to occur, that modify or delete user-controllable data in data storage systems, or that submit user test responses, the user can reverse, correct, or confirm the action.
+ +
+

3.3.7 Redundant Entry [AA]

+
Make it easier for users to complete multi-step processes. Don't ask for the same information twice in the same session.
+ +
+

3.3.8 Accessible Authentication (Minimum) [AA]

+
Make logins possible with less mental effort. Don't make people solve, recall, or transcribe something to log in.
+ +
+

4.1.1 Parsing [A]

+
(Obsolete and removed) This requirement was originally adopted to address problems that assistive technology (AT) had directly parsing HTML. AT no longer has any need to directly parse HTML. Consequently, these problems either no longer exist or are addressed by other requirements.
+ +
+

4.1.2 Name, Role, Value [A]

+
For all user interface components (including, but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies.
+ combobox_popup_reference: The 'aria-controls' (for ARIA 1.2) or the 'aria-owns' (for ARIA 1.0) attribute of the expanded combobox must reference a valid popup 'id' value + +  Violation — + The 'aria-owns' attribute of the expanded combobox is missing Violation — + The 'aria-controls' attribute of the expanded combobox is missing Violation — + The 'aria-owns' attribute "{0}" of the expanded combobox does not reference a valid popup 'id' value Violation — + The 'aria-controls' attribute "{0}" of the expanded combobox does not reference a valid popup 'id' value Violation — + The combobox 'aria-expanded' attribute is true, but the combobox popup is not visible Violation — + The combobox 'aria-expanded' attribute is false, but the combobox popup is visible + + aria_activedescendant_valid: The 'aria-activedescendant' property must reference the 'id' of a non-empty, non-hidden active child element + +  Violation — + The 'aria-activedescendant' property is empty Violation — + The 'aria-activedescendant' property references a hidden node Violation — + Element is not a combobox, and the referenced active-descendant element is not a valid descendant + + combobox_active_descendant: 'aria-activedescendant' must be used to define focus within the combobox popup, except when using a dialog popup + +  Violation — + The element referenced by 'aria-activedescendant' "{0}" does not exist Violation — + The 'aria-activedescendant' "{0}" references an element with the roles "{1}", which does not have a valid ARIA role of 'option', 'gridcell', 'row', or 'treeitem' Violation — + The 'aria-activedescendant' "{0}" references an element that does not have 'aria-selected' set to true + + input_haspopup_conflict: <input> element with a 'list' attribute should not use an explicit 'aria-haspopup' attribute + +  Needs review — + The <input> element with type "{0}" and 'list' attribute uses an explicit 'aria-haspopup' attribute Needs review — + The <input> element with a missing or invalid type and 'list' attribute uses an explicit 'aria-haspopup' attribute Needs review — + The list attribute for the <input> element is invalid Violation — + The list attribute for the <input> element with the type "{0}" is invalid Violation — + The list attribute for the <input> element does not reference a datalist element + + aria_role_valid: ARIA roles must be valid for the element to which they are assigned + +  Violation — + The ARIA role '{0}' is not valid for the element <{1}> Violation — + The ARIA role '{0}' is not valid for the element <{1}> and may be ignored by the browser since the element is focusable + + combobox_autocomplete_valid: A combobox that supports autocompletion behavior must have the 'aria-autocomplete' attribute only on its text input element with a valid value; a value of '"inline"' is not supported + +  Violation — + The combobox has the 'aria-autocomplete' attribute incorrectly set on an element within the popup referenced by "{0}" Violation — + The combobox does not support an 'aria-autocomplete' attribute value set to '"inline"' + + combobox_focusable_elements: Tabbable focus for the combobox must be allowed only on the text input, except when using a dialog popup + +  Violation — + The combobox element does not allow DOM focus as required Violation — + The popup of the combobox has DOM focus or has 'aria-activedescendant' defined, which is not allowed + + combobox_haspopup_valid: The combobox attribute 'aria-haspopup' value must be appropriate for the role of the element referenced by 'aria-controls' (ARIA 1.2) or 'aria-owns' (ARIA 1.0) + +  Violation — + The 'role' value "{0}" of the popup element "{1}" should be one of "listbox", "grid", "tree" or "dialog" Violation — + The value of the combobox 'aria-haspopup' attribute "{0}" does not match the 'role' value of the popup element "{1}" + + input_label_exists: Each form control must have an associated label + +  Violation — + Form control element <{0}> has no associated label Violation — + Form control with "{0}" role has no associated label + + aria_descendant_valid: Browsers ignore the explicit and implicit ARIA roles of the descendants of certain elements + +  Needs review — + The element with role "{0}" contains descendants with implicit roles "{1}" which are ignored by browsers Violation — + The element with role "{0}" contains descendants with roles "{1}" which are ignored by browsers + + aria_role_allowed: Elements must have a valid 'role' per ARIA specification + +  Violation — + The role '{0}' defined on the element is not valid per ARIA specification Needs review — + Some of the roles, '{0}', defined on the element are not valid per ARIA specification + + a_text_purpose: Hyperlinks must have an accessible name for their purpose + +  Violation — + Hyperlink has no link text, label or image with a text alternative + + aria_attribute_allowed: ARIA attributes must be valid for the element's role + +  Violation — + The attribute(s) '{0}' referenced by the element <{1}> is not a valid ARIA state or property + + aria_attribute_conflict: An ARIA attribute must not conflict with the corresponding HTML attribute + +  Violation — + The ARIA attribute "{0}" is in conflict with the corresponding HTML attribute "{1}" + + aria_attribute_exists: When specifying a required ARIA attribute, the value must not be empty + +  Violation — + The element attribute(s): '{0}' value is empty + + aria_attribute_required: The required attributes for the element with a role must be defined + +  Violation — + Element with '{0}' role does not have the required ARIA attribute(s): '{1}' + + aria_attribute_value_valid: ARIA property values must be valid + +  Violation — + The value "{0}" specified for attribute '{1}' on element <{2}> is not valid + + aria_eventhandler_role_valid: Elements with event handlers must have a valid ARIA role + +  Violation — + The <{0}> element with '{1}' does not have a valid ARIA role specified + + aria_hidden_nontabbable: A hidden element should not contain any tabbable elements + +  Violation — + Element "{0}" should not be focusable within the subtree of an element with an 'aria-hidden' attribute with value 'true' + + aria_id_unique: The ARIA property must reference a non-empty unique id of an existing element that is visible + +  Violation — + The 'id' "{0}" specified for the ARIA property '{1}' value is not valid + + aria_widget_labelled: Interactive component must have a programmatically associated name + +  Violation — + Interactive component with ARIA role '{0}' does not have a programmatically associated name + + combobox_design_valid: The combobox design pattern must be valid for ARIA 1.2 + +  Violation — + The combobox design pattern is detected as ARIA 1.1, which is not allowed by ARIA 1.2 + + element_tabbable_role_valid: A tabbable element must have a valid widget role + +  Violation — + The tabbable element's role '{0}' is not a widget role + + frame_title_exists: Inline frames must have a unique, non-empty 'title' attribute + +  Violation — + Inline frame does not have a 'title' attribute + + label_content_exists: A <label> element must have non-empty descriptive text that identifies the purpose of the interactive component + +  Violation — + The <label> element does not have descriptive text that identifies the expected input + + list_children_valid: List component with "group" role must limit children to <listitem> elements + +  Violation — + List component with "group" role has children that are not <listitem> elements + + table_aria_descendants: Table structure elements cannot specify an explicit 'role' within table containers + +  Violation — + An explicit ARIA 'role' is not valid for <{0}> element within an ARIA role '{1}' per the ARIA in HTML specification + + aria_accessiblename_exists: Elements with certain roles should have accessible names + +  Recommendation — + Element <{0}> with "{1}" role has no accessible name + + aria_attribute_redundant: An ARIA attribute should not be redundant with a corresponding HTML attribute + +  Recommendation — + The ARIA attribute "{0}" is redundant with the HTML attribute "{1}" + + canvas_content_described: The <canvas> element may not be accessible + +  Recommendation — + Verify accessibility of the <canvas> element + + +
+

4.1.3 Status Messages [AA]

+
In content implemented using markup languages, status messages can be programmatically determined through role or properties such that they can be presented to the user by assistive technologies without receiving focus.
+ +
+

HTML specification [NA]

+
The HTML specification issues that cause accessibility issues may be covered by other rules and will be reported under those accessibility requirements. However, some non-conforming HTML specification issues are still reported.
+ element_id_unique: Element 'id' attribute values must be unique within a document + +  Violation — + The <{0}> element has the id "{1}" that is empty Violation — + The <{0}> element has the id "{1}" that is already in use + + element_accesskey_unique: 'accesskey' attribute values on each element must be unique for the page + +  Violation — + 'accesskey' attribute value on the element is not unique + + element_attribute_deprecated: Avoid use of obsolete features if possible + +  Recommendation — + The <{0}> element is deprecated in HTML 5 Recommendation — + The HTML attribute(s) "{0}" is deprecated in HTML 5 Recommendation — + The HTML attribute(s) "{0}" is deprecated for the <{1}> element in HTML 5 + + +
+

ARIA specification [NA]

+
The ARIA specification issues that cause accessibility issues may be covered by other rules and will be reported under those accessibility requirements. However, some non-conforming ARIA specification issues are still reported.
+ aria_attribute_valid: ARIA attributes should be valid for the element and ARIA role to which they are assigned + +  Violation — + The ARIA attributes "{0}" are not valid for the element <{1}> with ARIA role "{2}" Violation — + The ARIA attributes "{0}" are not valid for the element <{1}> with implicit ARIA role "{2}" + + aria_attribute_deprecated: No deprecated ARIA role or attribute should be used + +  Recommendation — + The ARIA role "{0}" is deprecated in the ARIA specification Recommendation — + The ARIA attributes "{0}" are deprecated in the ARIA specification Recommendation — + The ARIA attributes "{0}" are deprecated for the role "{1}" in the ARIA specification + + aria_role_redundant: An explicitly-assigned ARIA role should not be redundant with the implicit role of the element + +  Recommendation — + The explicitly-assigned ARIA role "{0}" is redundant with the implicit role of the element <{1}> + + +
+
+
+ + \ No newline at end of file diff --git a/rule-server/src/static/archives/2024.08.29/js/ace-debug.js b/rule-server/src/static/archives/2024.08.29/js/ace-debug.js new file mode 100644 index 000000000..5165449cc --- /dev/null +++ b/rule-server/src/static/archives/2024.08.29/js/ace-debug.js @@ -0,0 +1,30682 @@ +/*! + * Copyright:: 2016,2017,2019,2020- IBM, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var ace; +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "./src/v2/aria/ARIADefinitions.ts": +/*!****************************************!*\ + !*** ./src/v2/aria/ARIADefinitions.ts ***! + \****************************************/ +/***/ ((__unused_webpack_module, exports) => { + + +/****************************************************************************** + Copyright:: 2020- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ARIADefinitions = void 0; +var ARIADefinitions = /** @class */ (function () { + function ARIADefinitions() { + } + ARIADefinitions.nameFromContent = function (role) { + return (role in ARIADefinitions.designPatterns) + && ARIADefinitions.designPatterns[role].nameFrom + && ARIADefinitions.designPatterns[role].nameFrom.includes("contents"); + }; + /* + * array of WAI-ARIA global states and properties + * @see https://www.w3.org/TR/wai-aria-1.2/#global_states + */ + ARIADefinitions.globalProperties = ["aria-atomic", "aria-busy", "aria-controls", "aria-current", "aria-describedby", + "aria-details", "aria-flowto", "aria-hidden", "aria-keyshortcuts", + "aria-label", "aria-labelledby", "aria-live", "aria-owns", "aria-relevant", "aria-roledescription" + // the following are deprecated in ARIA 1.2, will indicate deprecation in individual role + , + 'aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid' + ]; + //properties contains id(s) that refer to other element(s) + ARIADefinitions.referenceProperties = ["aria-owns", "aria-controls", "aria-describedby", "aria-labelledby", "aria-flowto", "aria-activedescendant"]; + // deprecated roles + ARIADefinitions.globalDeprecatedRoles = [ + 'directory', 'doc-biblioentry', 'doc-endnote' + ]; + // the following are deprecated in ARIA 1.1 for all the roles + ARIADefinitions.globalDeprecatedProperties = [ + 'aria-grabbed', 'aria-dropeffect' + ]; + /* + * XSD data types for all WAI-ARIA properties + * along with valid values when the data type is NMTOKEN + * WAI-ARIA properties data types explaned: + * type: Used to identify the type of values allowed for the WAI-ARIA property + * values: Used to identify specific values of an WAI-ARIA property when type is nmtoken + * hiddenIDRefSupported: Used to identify if the WAI-ARIA property supports referencing hidden ID + * true: refers to WAI-ARIA property supports hidden ID references + * false: refers to WAI-ARIA property does not support hidden ID references + * Default value will be set to false, if not specified. + */ + ARIADefinitions.propertyDataTypes = { + "aria-activedescendant": { + type: "http://www.w3.org/2001/XMLSchema#idref", + hiddenIDRefSupported: true + }, + "aria-atomic": { + type: "http://www.w3.org/2001/XMLSchema#boolean" + }, + "aria-autocomplete": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["inline", "list", "both", "none", "undefined"] //add undefined to handle value empty + }, + "aria-busy": { + type: "http://www.w3.org/2001/XMLSchema#boolean" + }, + "aria-checked": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["true", "false", "mixed", "undefined"] + }, + "aria-colcount": { + type: "http://www.w3.org/2001/XMLSchema#int" + }, + "aria-colindex": { + type: "http://www.w3.org/2001/XMLSchema#int" + }, + "aria-colspan": { + type: "http://www.w3.org/2001/XMLSchema#int" + }, + "aria-controls": { + type: "http://www.w3.org/2001/XMLSchema#idrefs", + hiddenIDRefSupported: true + }, + "aria-current": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["page", "step", "location", "date", "time", "true", "false", "undefined"] //add undefined for empty value + }, + "aria-describedby": { + type: "http://www.w3.org/2001/XMLSchema#idrefs", + hiddenIDRefSupported: true + }, + "aria-details": { + type: "http://www.w3.org/2001/XMLSchema#idrefs" + }, + "aria-disabled": { + type: "http://www.w3.org/2001/XMLSchema#boolean" + }, + "aria-dropeffect": { + type: "http://www.w3.org/2001/XMLSchema#nmtokens", + values: ["copy", "move", "link", "execute", "popup", "none"] + }, + "aria-errormessage": { + type: "http://www.w3.org/2001/XMLSchema#idref", + hiddenIDRefSupported: true + }, + "aria-expanded": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["true", "false", "undefined"] + }, + "aria-flowto": { + type: "http://www.w3.org/2001/XMLSchema#idrefs", + hiddenIDRefSupported: false + }, + "aria-grabbed": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["true", "false", "undefined"] + }, + "aria-haspopup": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["true", "false", "menu", "listbox", "tree", "grid", "dialog"] + }, + "aria-hidden": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["true", "false", "undefined"] + }, + "aria-invalid": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["true", "false", "spelling", "grammar", "undefined"] //add undefined for empty value + }, + "aria-keyshortcuts": { + type: "http://www.w3.org/2001/XMLSchema#string" + }, + "aria-label": { + type: "http://www.w3.org/2001/XMLSchema#string" + }, + "aria-labelledby": { + type: "http://www.w3.org/2001/XMLSchema#idrefs", + hiddenIDRefSupported: true + }, + "aria-level": { + type: "http://www.w3.org/2001/XMLSchema#int" + }, + "aria-live": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["off", "polite", "assertive"] + }, + "aria-modal": { + type: "http://www.w3.org/2001/XMLSchema#boolean" + }, + "aria-multiline": { + type: "http://www.w3.org/2001/XMLSchema#boolean" + }, + "aria-multiselectable": { + type: "http://www.w3.org/2001/XMLSchema#boolean" + }, + "aria-orientation": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["horizontal", "vertical", "undefined"] + }, + "aria-owns": { + type: "http://www.w3.org/2001/XMLSchema#idrefs", + hiddenIDRefSupported: true + }, + "aria-placeholder": { + type: "http://www.w3.org/2001/XMLSchema#string" + }, + "aria-posinset": { + type: "http://www.w3.org/2001/XMLSchema#int" + }, + "aria-pressed": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["true", "false", "mixed", "undefined"] + }, + "aria-readonly": { + type: "http://www.w3.org/2001/XMLSchema#boolean" + }, + "aria-relevant": { + type: "http://www.w3.org/2001/XMLSchema#nmtokens", + values: ["additions", "removals", "text", "all"] + }, + "aria-required": { + type: "http://www.w3.org/2001/XMLSchema#boolean" + }, + "aria-roledescription": { + type: "http://www.w3.org/2001/XMLSchema#string" + }, + "aria-rowcount": { + type: "http://www.w3.org/2001/XMLSchema#int" + }, + "aria-rowindex": { + type: "http://www.w3.org/2001/XMLSchema#int" + }, + "aria-rowspan": { + type: "http://www.w3.org/2001/XMLSchema#int" + }, + "aria-selected": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["true", "false", "undefined"] + }, + "aria-setsize": { + type: "http://www.w3.org/2001/XMLSchema#int" + }, + "aria-sort": { + type: "http://www.w3.org/2001/XMLSchema#nmtoken", + values: ["ascending", "descending", "other", "none"] + }, + "aria-valuemax": { + type: "http://www.w3.org/2001/XMLSchema#decimal" + }, + "aria-valuemin": { + type: "http://www.w3.org/2001/XMLSchema#decimal" + }, + "aria-valuenow": { + type: "http://www.w3.org/2001/XMLSchema#decimal" + }, + "aria-valuetext": { + type: "http://www.w3.org/2001/XMLSchema#string" + } + }; + /* + * design patterns for concrete WAI-ARIA roles + * legitimate keys for each role include: + * + * - container: appropriate container(s) for that role + * - props: states and properties that may be associated with this role (in addition to the global states and properties listed above) + * - reqProps: required states or properties for this role + * - reqChildren: required children for this role + * - htmlEquiv: HTML equivalent for this role + * - roleType: one of widget, structure, landmark, liveRegion, window (as seen in https://www.w3.org/TR/wai-aria-1.2/#roles_categorization) + * - nameRequired: determines whether an accessible name is required for a widget (see ARIA spec.) + * - nameFrom: determines how an accessible name is supplied (author or content - see ARIA spec.) + * - deprecated: if present, indicates that the role is deprecated, and provides a list of alternative role(s) + */ + ARIADefinitions.designPatterns = { + "alert": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "liveRegion", + nameRequired: false, + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "alertdialog": { + container: null, + props: ["aria-modal"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "window", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "application": { + container: null, + props: ["aria-activedescendant", "aria-expanded"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: true, + nameFrom: ["author"] + }, + "article": { + container: null, + props: ["aria-posinset", "aria-setsize"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "banner": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "blockquote": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "button": { + container: null, + props: ["aria-expanded", "aria-pressed"], + reqProps: null, + reqChildren: null, + htmlEquiv: "button | input[@type='button']", + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + presentationalChildren: true, + deprecatedProps: ['aria-errormessage', 'aria-invalid'] + }, + "caption": { + container: ["figure", "grid", "table", "treegrid"], + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "cell": { + container: ["row"], + props: ["aria-colindex", "aria-colspan", "aria-rowindex", "aria-rowspan"], + reqProps: null, + reqChildren: null, + htmlEquiv: "td", + roleType: "structure", + nameFrom: ["author", "contents"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "checkbox": { + container: null, + props: ["aria-expanded", "aria-readonly", "aria-required"], + reqProps: ["aria-checked"], + reqChildren: null, + htmlEquiv: "input[@type='checkbox']", + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + presentationalChildren: true, + deprecatedProps: ['aria-haspopup'] + }, + "code": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "columnheader": { + container: ["row"], + props: ["aria-colindex", "aria-colspan", "aria-expanded", "aria-readonly", "aria-required", "aria-rowindex", "aria-rowspan", "aria-selected", "aria-sort"], + reqProps: null, + reqChildren: null, + htmlEquiv: "th[@scope='col']", + roleType: "structure", + nameRequired: true, + nameFrom: ["author", "contents"] + }, + "combobox": { + container: null, + props: ["aria-controls", "aria-activedescendant", "aria-autocomplete", "aria-readonly", "aria-required"], + reqProps: ["aria-expanded"], + reqChildren: [], + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author"] + }, + "complementary": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "comment": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: false, + nameFrom: ["author", "contents"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "contentinfo": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "definition": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "deletion": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "dialog": { + container: null, + props: ["aria-modal"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "window", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "directory": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + deprecated: true, + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "doc-abstract": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-acknowledgments": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-afterword": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-appendix": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-backlink": { + container: null, + props: ["aria-disabled", "aria-expanded", "aria-haspopup"], + reqProps: null, + reqChildren: null, + htmlEquiv: "a | link", + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"] + }, + "doc-biblioentry": { + container: ["list"], + props: ["aria-level", "aria-posinset", "aria-setsize"], + reqProps: null, + reqChildren: null, + htmlEquiv: "li", + roleType: "structure", + nameRequired: true, + nameFrom: ["author"] + }, + "doc-bibliography": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-biblioref": { + container: null, + props: ["aria-disabled", "aria-expanded", "aria-haspopup"], + reqProps: null, + reqChildren: null, + htmlEquiv: "a | link", + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"] + }, + "doc-chapter": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-colophon": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: true, + nameFrom: ["author"] + }, + "doc-conclusion": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-cover": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: "img", + roleType: "structure", + nameRequired: false, + nameFrom: ["author"], + presentationalChildren: true + }, + "doc-credit": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-credits": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-dedication": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-endnote": { + container: ["list"], + props: ["aria-level", "aria-posinset", "aria-setsize"], + reqProps: null, + reqChildren: null, + htmlEquiv: "li", + roleType: "structure", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-endnotes": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: true, + nameFrom: ["author"] + }, + "doc-epigraph": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-epilogue": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-errata": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-example": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-footnote": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-foreword": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-glossary": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-glossref": { + container: null, + props: ["aria-disabled", "aria-expanded", "aria-haspopup"], + reqProps: null, + reqChildren: null, + htmlEquiv: "a | link", + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"] + }, + "doc-index": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-introduction": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-noteref": { + container: null, + props: ["aria-disabled", "aria-expanded", "aria-haspopup"], + reqProps: null, + reqChildren: null, + htmlEquiv: "a | link", + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"] + }, + "doc-notice": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-pagebreak": { + container: null, + props: ["aria-orientation"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: true, + nameFrom: ["author", "contents"], + presentationalChildren: true + }, + "doc-pagelist": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-pagefooter": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + }, + "doc-pageheader": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + }, + "doc-part": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-preface": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-prologue": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-pullquote": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-qna": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-subtitle": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: false, + nameFrom: ["author", "contents"] + }, + "doc-tip": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: false, + nameFrom: ["author"] + }, + "doc-toc": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: false, + nameFrom: ["author"] + }, + "document": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: false, + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "emphasis": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "feed": { + container: null, + props: null, + reqProps: null, + reqChildren: ["article"], + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "figure": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "form": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: "form", + roleType: "landmark", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "generic": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: "div | span", + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby", "aria-roledescription"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "graphics-document": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + nameRequired: true, + nameFrom: ["author"] + }, + "graphics-object": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + nameRequired: false, + nameFrom: ["author"] + }, + "graphics-symbol": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + nameRequired: true, + nameFrom: ["author"], + presentationalChildren: true + }, + "grid": { + container: null, + props: ["aria-activedescendant", "aria-colcount", "aria-multiselectable", "aria-readonly", "aria-rowcount"], + reqProps: null, + reqChildren: ["row", "rowgroup"], + htmlEquiv: "table", + roleType: "widget", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "gridcell": { + container: ["row"], + props: ["aria-colindex", "aria-colspan", "aria-disabled", "aria-errormessage", "aria-expanded", "aria-haspopup", "aria-invalid", "aria-readonly", "aria-required", "aria-rowindex", "aria-rowspan", "aria-selected"], + reqProps: null, + reqChildren: null, + htmlEquiv: "td", + roleType: "widget", + nameFrom: ["author", "contents"] + }, + "group": { + container: null, + props: ["aria-activedescendant"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "heading": { + container: null, + props: null, + reqProps: ["aria-level"], + reqChildren: null, + htmlEquiv: "h1 | h2 | h3 | h4 | h5 | h6", + roleType: "structure", + nameRequired: true, + nameFrom: ["author", "contents"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "img": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: "img", + roleType: "structure", + nameRequired: true, + nameFrom: ["author"], + presentationalChildren: true, + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "insertion": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "link": { + container: null, + props: ["aria-expanded"], + reqProps: null, + reqChildren: null, + htmlEquiv: "a | link", + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + deprecatedProps: ['aria-errormessage', 'aria-invalid'] + }, + "list": { + container: null, + props: null, + reqProps: null, + reqChildren: ["listitem"], + htmlEquiv: "ol | ul", + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "listbox": { + container: null, + props: ["aria-activedescendant", "aria-expanded", "aria-multiselectable", "aria-orientation", "aria-readonly", "aria-required"], + reqProps: null, + reqChildren: ["group", "option"], + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-haspopup'] + }, + "listitem": { + container: ["list"], + props: ["aria-level", "aria-posinset", "aria-setsize"], + reqProps: null, + reqChildren: null, + htmlEquiv: "li", + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "log": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "liveRegion", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "main": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "mark": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: "mark", + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "marquee": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "liveRegion", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "math": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + presentationalChildren: false, + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "menu": { + container: null, + props: ["aria-activedescendant", "aria-orientation"], + reqProps: null, + reqChildren: ["group", "menuitem", "menuitemcheckbox", "menuitemradio"], + htmlEquiv: null, + roleType: "widget", + nameRequired: false, + nameFrom: ["author"], + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "menubar": { + container: null, + props: ["aria-activedescendant", "aria-orientation"], + reqProps: null, + reqChildren: ["group", "menuitem", "menuitemcheckbox", "menuitemradio"], + htmlEquiv: null, + roleType: "widget", + nameRequired: false, + nameFrom: ["author"], + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "menuitem": { + container: ["group", "menu", "menubar"], + props: ["aria-expanded", "aria-posinset", "aria-setsize"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + deprecatedProps: ['aria-errormessage', 'aria-invalid'] + }, + "menuitemcheckbox": { + container: ["group", "menu", "menubar"], + props: ["aria-expanded", "aria-posinset", "aria-setsize"], + reqProps: ["aria-checked"], + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + presentationalChildren: true, + deprecatedProps: ['aria-errormessage', 'aria-invalid'] + }, + "menuitemradio": { + container: ["group", "menu", "menubar"], + props: ["aria-expanded", "aria-posinset", "aria-setsize"], + reqProps: ["aria-checked"], + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + presentationalChildren: true, + deprecatedProps: ['aria-errormessage', 'aria-invalid'] + }, + "meter": { + container: null, + props: ["aria-valuemax", "aria-valuemin", "aria-valuetext"], + reqProps: ["aria-valuenow"], + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: true, + nameFrom: ["author"], + presentationalChildren: true, + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "navigation": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "none": { + container: null, + props: [], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "note": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "option": { + container: ["group", "listbox"], + props: ["aria-selected", "aria-checked", "aria-posinset", "aria-setsize"], + reqProps: null, + reqChildren: null, + htmlEquiv: "option", + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + presentationalChildren: true, + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "paragraph": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "presentation": { + container: null, + props: [], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "progressbar": { + container: null, + props: ["aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-valuetext"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author"], + presentationalChildren: true, + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "radio": { + container: null, + props: ["aria-posinset", "aria-setsize"], + reqProps: ["aria-checked"], + reqChildren: null, + htmlEquiv: "input[@type='radio']", + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + presentationalChildren: true, + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "radiogroup": { + container: null, + props: ["aria-activedescendant", "aria-orientation", "aria-readonly", "aria-required"], + reqProps: null, + reqChildren: ["radio"], + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-haspopup'] + }, + "region": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "row": { + container: ["grid", "rowgroup", "table", "treegrid"], + props: ["aria-activedescendant", "aria-colindex", "aria-expanded", "aria-level", "aria-posinset", "aria-rowindex", "aria-selected", "aria-setsize"], + reqProps: null, + reqChildren: ["cell", "columnheader", "gridcell", "rowheader"], + htmlEquiv: "tr", + roleType: "structure", + nameFrom: ["author", "contents"], + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "rowgroup": { + container: ["grid", "table", "treegrid"], + props: [], + reqProps: null, + reqChildren: ["row"], + htmlEquiv: "tbody | tfoot | thead", + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "rowheader": { + container: ["row"], + props: ["aria-colindex", "aria-colspan", "aria-expanded", "aria-readonly", "aria-required", "aria-rowindex", "aria-rowspan", "aria-selected", "aria-sort"], + reqProps: null, + reqChildren: null, + htmlEquiv: "th[@scope='row']", + roleType: "structure", + nameRequired: true, + nameFrom: ["author", "contents"] + }, + "scrollbar": { + container: null, + props: ["aria-orientation", "aria-valuemax", "aria-valuemin", "aria-valuetext"], + reqProps: ["aria-controls", "aria-valuenow"], + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: false, + nameFrom: ["author"], + presentationalChildren: true, + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "search": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "landmark", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "searchbox": { + container: null, + props: ["aria-activedescendant", "aria-autocomplete", "aria-multiline", "aria-placeholder", "aria-readonly", "aria-required"], + reqProps: null, + reqChildren: null, + htmlEquiv: "input[@type='search']", + roleType: "widget", + nameRequired: true, + nameFrom: ["author"] + }, + "separator": { + container: null, + props: ["aria-orientation"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + presentationalChildren: true, + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "slider": { + container: null, + props: ["aria-orientation", "aria-readonly", "aria-valuemax", "aria-valuemin", "aria-valuetext"], + reqProps: ["aria-valuenow"], + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author"], + presentationalChildren: true + }, + "spinbutton": { + container: null, + props: ["aria-activedescendant", "aria-readonly", "aria-required", "aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-valuetext"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-haspopup'] + }, + "status": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "liveRegion", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "strong": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "subscript": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "suggestion": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "superscript": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "switch": { + container: null, + props: ["aria-expanded", "aria-readonly", "aria-required"], + reqProps: ["aria-checked"], + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + presentationalChildren: true, + deprecatedProps: ['aria-haspopup'] + }, + "tab": { + container: ["tablist"], + props: ["aria-expanded", "aria-posinset", "aria-selected", "aria-setsize"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + presentationalChildren: true, + deprecatedProps: ['aria-errormessage', 'aria-invalid'] + }, + "table": { + container: null, + props: ["aria-colcount", "aria-rowcount"], + reqProps: null, + reqChildren: ["row", "rowgroup", "caption"], + htmlEquiv: "table", + roleType: "structure", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "tablist": { + container: null, + props: ["aria-activedescendant", "aria-multiselectable", "aria-orientation"], + reqProps: null, + reqChildren: ["tab"], + htmlEquiv: null, + roleType: "widget", + nameRequired: false, + nameFrom: ["author"], + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "tabpanel": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "term": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: "dfn", + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "textbox": { + container: null, + props: ["aria-activedescendant", "aria-autocomplete", "aria-multiline", "aria-placeholder", "aria-readonly", "aria-required"], + reqProps: null, + reqChildren: null, + htmlEquiv: "input[@type='text']", + roleType: "widget", + nameRequired: true, + nameFrom: ["author"] + }, + "time": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["prohibited"], + prohibitedProps: ["aria-label", "aria-labelledby"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "timer": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "liveRegion", + nameFrom: ["author"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "toolbar": { + container: null, + props: ["aria-activedescendant", "aria-orientation"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameFrom: ["author"], + deprecatedProps: ['aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "tooltip": { + container: null, + props: null, + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "structure", + nameRequired: false, + nameFrom: ["author", "contents"], + deprecatedProps: ['aria-disabled', 'aria-errormessage', 'aria-haspopup', 'aria-invalid'] + }, + "tree": { + container: null, + props: ["aria-activedescendant", "aria-multiselectable", "aria-orientation", "aria-required"], + reqProps: null, + reqChildren: ["group", "treeitem"], + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-haspopup'] + }, + "treegrid": { + container: null, + props: ["aria-activedescendant", "aria-colcount", "aria-multiselectable", "aria-orientation", "aria-readonly", "aria-required", "aria-rowcount"], + reqProps: null, + reqChildren: ["row", "rowgroup"], + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author"], + deprecatedProps: ['aria-haspopup'] + }, + "treeitem": { + container: ["group", "tree"], + props: ["aria-checked", "aria-expanded", "aria-level", "aria-posinset", "aria-selected", "aria-setsize"], + reqProps: null, + reqChildren: null, + htmlEquiv: null, + roleType: "widget", + nameRequired: true, + nameFrom: ["author", "contents"], + deprecatedProps: ['aria-errormessage', 'aria-invalid'] + }, + }; // end designPatterns + // copied from https://html.spec.whatwg.org/multipage/semantics-other.html#disabled-elements + // https://html.spec.whatwg.org/multipage/input.html#input-type-attr-summary + ARIADefinitions.elementsAllowedDisabled = ["button", "input", "select", "textarea", "optgroup", "option", "fieldset"]; // also form-associated custom element + ARIADefinitions.elementsAllowedRequired = ["select", "textarea"]; // remove 'input' and add to the individual element, becuase required is not supported on input@type="range", "color", "hidden" or any button types + ARIADefinitions.elementsAllowedReadOnly = ["textarea"]; // remove 'input' and add to the individual element, because readonly is not supported on input@type="checkbox", "radio", "range", "color", "file", hidden" or any button types + /* https://www.w3.org/TR/html-aria/#docconformance + * documentConformanceRequirement contains properties of the tags related to role without any additional attribute value + * documentConformanceRequirementSpecialTags contains those tags that require special considerations + */ + ARIADefinitions.documentConformanceRequirement = { + "abbr": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true, + prohibitedAriaAttributesWhenNoImplicitRole: ["aria-label", "aria-labelledby"] + }, + "address": { + implicitRole: ["group"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "article": { + implicitRole: ["article"], + validRoles: ["application", "document", "feed", "main", "none", "presentation", "region"], + globalAriaAttributesValid: true + }, + "aside": { + implicitRole: ["complementary"], + validRoles: ["doc-dedication", "doc-example", "doc-footnote", "doc-glossary", "doc-pullquote", "doc-tip", "feed", "none", "note", "presentation", "region", "search"], + globalAriaAttributesValid: true + }, + "audio": { + implicitRole: null, + validRoles: ["application"], + globalAriaAttributesValid: true + }, + "b": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "base": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "bdi": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "bdo": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "blockquote": { + implicitRole: ["blockquote"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "body": { + implicitRole: ["generic"], + validRoles: null, + otherDisallowedAriaAttributes: ['aria-hidden'], + globalAriaAttributesValid: true + }, + "br": { + implicitRole: null, + validRoles: ["none", "presentation"], + globalAriaAttributesValid: false, + otherAllowedAriaAttributes: ["aria-hidden"] + }, + "button": { + implicitRole: ["button"], + validRoles: ["checkbox", "combobox", "gridcell", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "slider", "switch", "tab", "treeitem"], + globalAriaAttributesValid: true + }, + "canvas": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "caption": { + implicitRole: ['caption'], + validRoles: null, + globalAriaAttributesValid: true, + allowAttributesFromImplicitRole: false + }, + "cite": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true, + prohibitedAriaAttributesWhenNoImplicitRole: ["aria-label", "aria-labelledby"] + }, + "code": { + implicitRole: ["code"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "col": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "colgroup": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "data": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "datalist": { + implicitRole: ["listbox"], + validRoles: null, + globalAriaAttributesValid: false, + allowAttributesFromImplicitRole: false + }, + "dd": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true + }, + "del": { + implicitRole: ["deletion"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "details": { + implicitRole: ["group"], + validRoles: null, + globalAriaAttributesValid: true + }, + "dfn": { + implicitRole: ["term"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "dialog": { + implicitRole: ["dialog"], + validRoles: ["alertdialog"], + globalAriaAttributesValid: true + }, + "dl": { + implicitRole: null, + validRoles: ["group", "list", "none", "presentation"], + globalAriaAttributesValid: true + }, + "dt": { + implicitRole: ["term"], + validRoles: ["listitem"], + globalAriaAttributesValid: true + }, + "em": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "embed": { + implicitRole: null, + validRoles: ["application", "document", "img", "none", "presentation"], + globalAriaAttributesValid: true + }, + "fieldset": { + implicitRole: ["group"], + validRoles: ["none", "presentation", "radiogroup"], + globalAriaAttributesValid: true + }, + "figcaption": { + implicitRole: null, + validRoles: ["group", "none", "presentation"], + globalAriaAttributesValid: true, + prohibitedAriaAttributesWhenNoImplicitRole: ["aria-label", "aria-labelledby"] + }, + "form": { + implicitRole: ["form"], + validRoles: ["none", "presentation", "search"], + globalAriaAttributesValid: true + }, + "head": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "hgroup": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "h1": { + implicitRole: ["heading"], + validRoles: ["doc-subtitle", "none", "presentation", "tab"], + globalAriaAttributesValid: true + }, + "h2": { + implicitRole: ["heading"], + validRoles: ["doc-subtitle", "none", "presentation", "tab"], + globalAriaAttributesValid: true + }, + "h3": { + implicitRole: ["heading"], + validRoles: ["doc-subtitle", "none", "presentation", "tab"], + globalAriaAttributesValid: true + }, + "h4": { + implicitRole: ["heading"], + validRoles: ["doc-subtitle", "none", "presentation", "tab"], + globalAriaAttributesValid: true + }, + "h5": { + implicitRole: ["heading"], + validRoles: ["doc-subtitle", "none", "presentation", "tab"], + globalAriaAttributesValid: true + }, + "h6": { + implicitRole: ["heading"], + validRoles: ["doc-subtitle", "none", "presentation", "tab"], + globalAriaAttributesValid: true + }, + "hr": { + implicitRole: ["separator"], + validRoles: ["doc-pagebreak", "none", "presentation"], + globalAriaAttributesValid: true + }, + "html": { + implicitRole: ["document"], + validRoles: null, + globalAriaAttributesValid: false, + allowAttributesFromImplicitRole: false + }, + "i": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "iframe": { + implicitRole: null, + validRoles: ["application", "document", "img", "none", "presentation"], + globalAriaAttributesValid: true + }, + "ins": { + implicitRole: ["insertion"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "kbd": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true, + prohibitedAriaAttributesWhenNoImplicitRole: ["aria-label", "aria-labelledby"] + }, + "label": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + prohibitedAriaAttributesWhenNoImplicitRole: ["aria-label", "aria-labelledby"] + }, + "legend": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + prohibitedAriaAttributesWhenNoImplicitRole: ["aria-label", "aria-labelledby"] + }, + "link": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "main": { + implicitRole: ["main"], + validRoles: null, + globalAriaAttributesValid: true + }, + "map": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "mark": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true, + prohibitedAriaAttributesWhenNoImplicitRole: ["aria-label", "aria-labelledby"] + }, + "math": { + implicitRole: ["math"], + validRoles: null, + globalAriaAttributesValid: true + }, + "menu": { + implicitRole: ["list"], + validRoles: ["group", "listbox", "menu", "menubar", "none", "presentation", "radiogroup", "tablist", "toolbar", "tree"], + globalAriaAttributesValid: true + }, + "meta": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "meter": { + implicitRole: ["meter"], + validRoles: null, + globalAriaAttributesValid: true, + otherDisallowedAriaAttributes: ['aria-valuemax', 'aria-valuemin'], + allowAttributesFromImplicitRole: false + }, + "nav": { + implicitRole: ["navigation"], + validRoles: ["doc-index", "doc-pagelist", "doc-toc", "menu", "menubar", "tablist", "none", "presentation"], + globalAriaAttributesValid: true + }, + "noscript": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "object": { + implicitRole: null, + validRoles: ["application", "document", "img"], + globalAriaAttributesValid: true + }, + "ol": { + implicitRole: ["list"], + validRoles: ["group", "listbox", "menu", "menubar", "none", "presentation", "radiogroup", "tablist", "toolbar", "tree"], + globalAriaAttributesValid: true + }, + "optgroup": { + implicitRole: ["group"], + validRoles: null, + globalAriaAttributesValid: true + }, + "option": { + implicitRole: ["option"], + validRoles: null, + globalAriaAttributesValid: true, + otherDisallowedAriaAttributes: ["aria-selected"] + }, + "output": { + implicitRole: ["status"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "p": { + implicitRole: ["paragraph"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "param": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "picture": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false, + otherAllowedAriaAttributes: ["aria-hidden"] + }, + "pre": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "progress": { + implicitRole: ["progressbar"], + validRoles: null, + globalAriaAttributesValid: true, + otherDisallowedAriaAttributes: ["aria-valuemax"] + }, + "q": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "rp": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "rt": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true, + prohibitedAriaAttributesWhenNoImplicitRole: ["aria-label", "aria-labelledby"] + }, + "ruby": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "s": { + implicitRole: ["deletion"], + validRoles: ["any"], + globalAriaAttributesValid: true, + otherDisallowedAriaAttributes: ["aria-label", "aria-labelledby"] + }, + "samp": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "script": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "search": { + implicitRole: ['search'], + validRoles: ['search', 'form', 'group', 'none', 'presentation', 'region'], + globalAriaAttributesValid: true + }, + "slot": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "small": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "source": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "span": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "strong": { + implicitRole: ["strong"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "style": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "sub": { + implicitRole: ["subscript"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "sup": { + implicitRole: ["superscript"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "svg": { + implicitRole: ["graphics-document"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "table": { + implicitRole: ["table"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "template": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "textarea": { + implicitRole: ["textbox"], + validRoles: null, + globalAriaAttributesValid: true + }, + "tfoot": { + implicitRole: ["rowgroup"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "thead": { + implicitRole: ["rowgroup"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "time": { + implicitRole: ["time"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "title": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "track": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "u": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "ul": { + implicitRole: ["list"], + validRoles: ["group", "listbox", "menu", "menubar", "none", "presentation", "radiogroup", "tablist", "toolbar", "tree"], + globalAriaAttributesValid: true + }, + "var": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true, + prohibitedAriaAttributesWhenNoImplicitRole: ["aria-label", "aria-labelledby"] + }, + "video": { + implicitRole: null, + validRoles: ["application"], + globalAriaAttributesValid: true + }, + "wbr": { + implicitRole: null, + validRoles: ["none", "presentation"], + globalAriaAttributesValid: false, + otherAllowedAriaAttributes: ["aria-hidden"] + } + }; // end documentConformanceRequirement + ARIADefinitions.documentConformanceRequirementSpecialTags = { + "a": { + "with-href": { + implicitRole: ["link"], + //roleCondition: " when non-empty href attribute is present", + validRoles: ["button", "checkbox", "doc-backlink", "doc-biblioref", "doc-glossref", "doc-noteref", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "switch", "tab", "treeitem"], + globalAriaAttributesValid: true, + otherDisallowedAriaAttributes: ["aria-disabled=true"] + }, + "without-href": { + implicitRole: ["generic"], + //roleCondition: " when href attribute is not present", + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, + "area": { + "with-href": { + implicitRole: ["link"], + //roleCondition: " when non-empty href attribute is present", + validRoles: null, + globalAriaAttributesValid: true + }, + "without-href": { + implicitRole: ["generic"], + //roleCondition: " when href attribute is not present", + validRoles: ["button", "link"], + globalAriaAttributesValid: true + } + }, + // TODO + // "autonomous custom element": { + // implicitRole: ["Role exposed from author defined ElementInternals. Otherwise no corresponding role."], + // validRoles: ["If role defined by ElementInternals", "any role", "no role Otherwise"], + // globalAriaAttributesValid: true + // }, + "div": { + "child-dl": { + implicitRole: ["generic"], + validRoles: ["presentation", "none"], + globalAriaAttributesValid: true + }, + "no-child-dl": { + implicitRole: ["generic"], + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, + "figure": { + "child-figcaption": { + implicitRole: ["figure"], + validRoles: ['doc-example'], + globalAriaAttributesValid: true + }, + "no-child-figcaption": { + implicitRole: ["figure"], + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, + "footer": { + "des-section-article-aside-main-nav": { + implicitRole: ["generic"], + //roleCondition: " when descendant of an article, aside, main, nav or section element", + validRoles: ["doc-footnote", "group", "none", "presentation"], + globalAriaAttributesValid: true + }, + "other": { + implicitRole: ["contentinfo"], + //roleCondition: " when not a descendant of an article, aside, main, nav or section element", + validRoles: ["doc-footnote", "group", "none", "presentation"], + globalAriaAttributesValid: true + } + }, + // TODO + // "form-associated custom element": { + // implicitRole: ["Role exposed from author defined ElementInternals. Otherwise 'generic'."], + // validRoles: ["If role defined by ElementInternals", "form-related roles: button", "checkbox", "combobox", "group", "listbox", "progressbar", "radio", "radiogroup", "searchbox", "slider", "spinbutton", "switch", "textbox", "no role Otherwise"], + // globalAriaAttributesValid: true + // }, + "header": { + "des-section-article-aside-main-nav": { + implicitRole: ["generic"], + //roleCondition: " when descendant of an article, aside, main, nav or section element", + validRoles: ["group", "none", "presentation"], + globalAriaAttributesValid: true + }, + "other": { + implicitRole: ["banner"], + //roleCondition: " when not a descendant of an article, aside, main, nav or section element", + validRoles: ["group", "none", "presentation"], + globalAriaAttributesValid: true + } + }, + "img": { + "img-with-accname": { + implicitRole: ["img"], + //roleCondition: "when accessible name presents", + validRoles: ["button", "checkbox", "doc-cover", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "meter", "option", "progressbar", "radio", "scrollbar", "separator", "slider", "switch", "tab", "treeitem"], + globalAriaAttributesValid: true + }, + "img-without-accname-empty-alt": { + implicitRole: ["presentation", "none"], + //roleCondition: "when no accessible name presents and alt=''", + validRoles: null, + globalAriaAttributesValid: false, + otherAllowedAriaAttributes: ["aria-hidden=true"] + }, + "img-without-accname-no-alt": { + implicitRole: ["img"], + //roleCondition: "when neither accessible name no alt presents", + validRoles: ["presentation", "none"], + globalAriaAttributesValid: false, + otherAllowedAriaAttributes: ["aria-hidden=true"] + } + }, + "input": { + "button": { + implicitRole: ["button"], + validRoles: ["checkbox", "combobox", "gridcell", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "slider", "switch", "tab", "treeitem"], + globalAriaAttributesValid: true + }, + "checkbox-with-aria-pressed": { + implicitRole: ["checkbox"], + //roleCondition: " with type=checkbox and aria-pressed attribute is present", + validRoles: ["menuitemcheckbox", "option", "switch", "button"], + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-required"], + otherDisallowedAriaAttributes: ["aria-checked"] + }, + "checkbox-without-aria-pressed": { + implicitRole: ["checkbox"], + //roleCondition: " with type=checkbox and aria-pressed attribute is not present", + validRoles: ["menuitemcheckbox", "option", "switch"], + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-required"], + otherDisallowedAriaAttributes: ["aria-checked"] + }, + "color": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true + }, + "date": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-required", "aria-readonly"], + otherRolesForAttributes: ["textbox"] + }, + "datetime-local": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-required", "aria-readonly"], + otherRolesForAttributes: ["textbox"] + }, + "email-no-list": { + implicitRole: ["textbox"], + //roleCondition: " with type=email and no list attribute is present", + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-placeholder", "aria-required", "aria-readonly"], + otherRolesForAttributes: ["textbox"] + }, + "email-with-list": { + implicitRole: ["combobox"], + validRoles: null, + globalAriaAttributesValid: true + }, + "file": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-required"], + }, + "hidden": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: false + }, + "image": { + implicitRole: ["button"], + validRoles: ["checkbox", "gridcell", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "slider", "switch", "tab", "treeitem"], + globalAriaAttributesValid: true + }, + "month": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-readonly"], + otherRolesForAttributes: ["textbox"] + }, + "number": { + implicitRole: ["spinbutton"], + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-placeholder", "aria-required", "aria-readonly"], + }, + "password": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-placeholder", "aria-required", "aria-readonly"], + otherRolesForAttributes: ["textbox"] + }, + "radio": { + implicitRole: ["radio"], + validRoles: ["menuitemradio"], + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-required"], + otherDisallowedAriaAttributes: ["aria-checked"] + }, + "range": { + implicitRole: ["slider"], + validRoles: null, + globalAriaAttributesValid: true, + otherDisallowedAriaAttributes: ["aria-valuemax", "aria-valuemin"] + }, + "reset": { + implicitRole: ["button"], + validRoles: ["checkbox", "combobox", "gridcell", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "slider", "switch", "tab", "treeitem"], + globalAriaAttributesValid: true + }, + "search-no-list": { + implicitRole: ["searchbox"], + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-placeholder", "aria-required", "aria-readonly"] + }, + "search-with-list": { + implicitRole: ["combobox"], + validRoles: null, + globalAriaAttributesValid: true + }, + "submit": { + implicitRole: ["button"], + validRoles: ["checkbox", "combobox", "gridcell", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "slider", "switch", "tab", "treeitem"], + globalAriaAttributesValid: true + }, + "tel-no-list": { + implicitRole: ["textbox"], + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-placeholder", "aria-required", "aria-readonly"] + }, + "tel-with-list": { + implicitRole: ["combobox"], + validRoles: null, + globalAriaAttributesValid: true + }, + "text-no-list": { + implicitRole: ["textbox"], + validRoles: ["combobox", "searchbox", "spinbutton"], + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-placeholder", "aria-required", "aria-readonly"] + }, + "text-with-list": { + implicitRole: ["combobox"], + validRoles: null, + globalAriaAttributesValid: true + // otherDisallowedAriaAttributes: ["aria-haspopup"] // covered in a different rule + }, + "time": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-readonly"], + otherRolesForAttributes: ["textbox"] + }, + "url-no-list": { + implicitRole: ["textbox"], + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-placeholder", "aria-required", "aria-readonly"] + }, + "url-with-list": { + implicitRole: ["combobox"], + validRoles: null, + globalAriaAttributesValid: true + }, + "week": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-readonly"], + otherRolesForAttributes: ["textbox"] + }, + "default-with-list": { + // input with a missing or invalid type, with a list attribute + implicitRole: ["combobox"], + validRoles: null, + globalAriaAttributesValid: true + }, + "default-no-list": { + // input with a missing or invalid type, with a list attribute + implicitRole: ["textbox"], + validRoles: null, + globalAriaAttributesValid: true + } + }, + "li": { + "child-of-list-role": { + implicitRole: ['listitem'], + validRoles: null, + globalAriaAttributesValid: true + }, + "no-child-of-list-role": { + implicitRole: ['generic'], + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, + "section": { + "with-name": { + implicitRole: ["region"], + validRoles: ["alert", "alertdialog", "application", "banner", "complementary", "contentinfo", "dialog", "doc-abstract", "doc-acknowledgments", "doc-afterword", "doc-appendix", "doc-bibliography", "doc-chapter", "doc-colophon", "doc-conclusion", "doc-credit", "doc-credits", "doc-dedication", "doc-endnotes", "doc-epigraph", "doc-epilogue", "doc-errata", "doc-example", "doc-foreword", "doc-glossary", "doc-index", "doc-introduction", "doc-notice", "doc-pagelist", "doc-part", "doc-preface", "doc-prologue", "doc-pullquote", "doc-qna", "doc-toc", "document", "feed", "group", "log", "main", "marquee", "navigation", "none", "note", "presentation", "search", "status", "tabpanel"], + globalAriaAttributesValid: true + }, + "without-name": { + implicitRole: null, + validRoles: ["alert", "alertdialog", "application", "banner", "complementary", "contentinfo", "dialog", "doc-abstract", "doc-acknowledgments", "doc-afterword", "doc-appendix", "doc-bibliography", "doc-chapter", "doc-colophon", "doc-conclusion", "doc-credit", "doc-credits", "doc-dedication", "doc-endnotes", "doc-epigraph", "doc-epilogue", "doc-errata", "doc-example", "doc-foreword", "doc-glossary", "doc-index", "doc-introduction", "doc-notice", "doc-pagelist", "doc-part", "doc-preface", "doc-prologue", "doc-pullquote", "doc-qna", "doc-toc", "document", "feed", "group", "log", "main", "marquee", "navigation", "none", "note", "presentation", "search", "status", "tabpanel"], + globalAriaAttributesValid: true + } + }, + "select": { + "no-multiple-attr-size-gt1": { + //roleCondition: " with a multiple attribute or a size attribute having value greater than 1" + implicitRole: ["combobox"], + validRoles: ["menu"], + globalAriaAttributesValid: true, + otherDisallowedAriaAttributes: ["aria-multiselectable"] + }, + "multiple-attr-size-gt1": { + //roleCondition: " with no multiple attribute and no size attribute having value greater than 1" + implicitRole: ["listbox"], + validRoles: null, + globalAriaAttributesValid: true, + otherDisallowedAriaAttributes: ["aria-multiselectable"] + } + }, + "summary": { + "first-summary-of-detail": { + implicitRole: null, + validRoles: null, + globalAriaAttributesValid: true, + otherAllowedAriaAttributes: ["aria-disabled", "aria-haspopup"] + }, + "no-first-summary-of-detail": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, + "tbody": { + "des-table": { + implicitRole: ["rowgroup"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "des-grid": { + implicitRole: ["rowgroup"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "des-treegrid": { + implicitRole: ["rowgroup"], + validRoles: ["any"], + globalAriaAttributesValid: true + }, + "des-other": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, + "td": { + "des-table": { + implicitRole: ["cell"], + validRoles: null, + globalAriaAttributesValid: true + }, + "des-grid": { + implicitRole: ["gridcell"], + validRoles: null, + globalAriaAttributesValid: true + }, + "des-treegrid": { + implicitRole: ["gridcell"], + validRoles: null, + globalAriaAttributesValid: true + }, + "des-other": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, + "th": { + "des-table-grid-treegrid-row-scope": { + implicitRole: ["rowheader", "cell"], + validRoles: null, + globalAriaAttributesValid: true + }, + "des-table-grid-treegrid-column-scope": { + implicitRole: ["columnheader", "cell"], + validRoles: null, + globalAriaAttributesValid: true + }, + "des-other": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, + "tr": { + "des-table": { + implicitRole: ["row"], + validRoles: null, + globalAriaAttributesValid: true + }, + "des-grid": { + implicitRole: ["row"], + validRoles: null, + globalAriaAttributesValid: true + }, + "des-treegrid": { + implicitRole: ["row"], + validRoles: null, + globalAriaAttributesValid: true + }, + "des-other": { + implicitRole: null, + validRoles: ["any"], + globalAriaAttributesValid: true + } + }, + "default": { + implicitRole: null, + //roleCondition: "", + validRoles: ["any"], + globalAriaAttributesValid: true + } + }; // end of documentConformanceRequirementSpecialTags + // map aria attribute to the corresponding native attribute, apply to any element applicable + // note this mapping is for the related attributes in the same element without checking the parent tree. + // refer to https://w3c.github.io/html-aria/ + ARIADefinitions.relatedAriaHtmlAttributes = { + "aria-checked": { + conflict: [{ + ariaAttributeValue: "false", + htmlAttributeNames: ["checked"], + htmlAttributeValues: null + }], + overlapping: [{ + ariaAttributeValue: "true", + htmlAttributeNames: ["checked"], + htmlAttributeValues: null + }] + }, + "aria-disabled": { + conflict: [{ + ariaAttributeValue: "false", + htmlAttributeNames: ["disabled"], + htmlAttributeValues: null + }], + overlapping: [{ + ariaAttributeValue: "true", + htmlAttributeNames: ["disabled"], + htmlAttributeValues: null + }] + }, + "aria-hidden": { + conflict: [{ + ariaAttributeValue: "false", + htmlAttributeNames: ["hidden"], + htmlAttributeValues: ["hidden,null"] + }, + { + ariaAttributeValue: "true", + htmlAttributeNames: ["hidden"], + htmlAttributeValues: ["until-found"] + }], + overlapping: [{ + ariaAttributeValue: "true", + htmlAttributeNames: ["hidden"], + htmlAttributeValues: ["hidden,null"] + }] + }, + "aria-placeholder": { + conflict: [{ + ariaAttributeValue: null, + htmlAttributeNames: ["placeholder"], + htmlAttributeValues: null + }] + }, + "aria-valuemax": { + conflict: [{ + ariaAttributeValue: null, + htmlAttributeNames: ["max"], + htmlAttributeValues: null + }] + //overlap case covered in the role definition: Authors SHOULD NOT use aria-valuemax on any element which allows the max attribute. Use the max attribute instead. + }, + "aria-valuemin": { + conflict: [{ + ariaAttributeValue: null, + htmlAttributeNames: ["min"], + htmlAttributeValues: null + }] + ////overlap case covered in the role definition:Authors SHOULD NOT use aria-valuemin on any element which allows the min attribute. Use the min attribute instead. + }, + "aria-readonly": { + conflict: [{ + ariaAttributeValue: "false", + htmlAttributeNames: ["readonly", "contenteditable", "iscontenteditable"], + htmlAttributeValues: [null, "false", "false"] + }], + overlapping: [{ + ariaAttributeValue: "true", + htmlAttributeNames: ["readonly", "contenteditable", "iscontenteditable"], + htmlAttributeValues: [null, "true", "true"] + }] + }, + "aria-required": { + conflict: [{ + ariaAttributeValue: "false", + htmlAttributeNames: ["required"], + htmlAttributeValues: null + }], + overlapping: [{ + ariaAttributeValue: "true", + htmlAttributeNames: ["required"], + htmlAttributeValues: null + }] + }, + "aria-colspan": { + conflict: [{ + // conflict occurs if both values are different + ariaAttributeValue: "VALUE", + htmlAttributeNames: ["colspan"], + htmlAttributeValues: ["VALUE"] + }], + overlapping: [{ + // overlap occurs if both exists + ariaAttributeValue: null, + htmlAttributeNames: ["colspan"], + htmlAttributeValues: null + }] + }, + "aria-rowspan": { + conflict: [{ + // conflict occurs if both values are different + ariaAttributeValue: "VALUE", + htmlAttributeNames: ["rowspan"], + htmlAttributeValues: ["VALUE"] + }], + overlapping: [{ + // overlap occurs if both exists + ariaAttributeValue: null, + htmlAttributeNames: ["rowspan"], + htmlAttributeValues: null + }] + }, + "aria-autocomplete": { + conflict: [{ + // conflict occurs if both exists, aria value is only for custom widget, rather than native + ariaAttributeValue: null, + htmlAttributeNames: ["autocomplete"], + htmlAttributeValues: null + }] + } + }; + ARIADefinitions.containers = []; + return ARIADefinitions; +}()); +exports.ARIADefinitions = ARIADefinitions; +; +var containerArray = []; +for (var roleDesign in ARIADefinitions.designPatterns) { + var containers = ARIADefinitions.designPatterns[roleDesign].container; + if (containers !== null) { + for (var _i = 0, containers_1 = containers; _i < containers_1.length; _i++) { + var container = containers_1[_i]; + if (containerArray.indexOf(container) == -1) { + containerArray.push(container); + } + } + } +} +ARIADefinitions.containers = containerArray; + + +/***/ }), + +/***/ "./src/v2/aria/ARIAMapper.ts": +/*!***********************************!*\ + !*** ./src/v2/aria/ARIAMapper.ts ***! + \***********************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +/****************************************************************************** + Copyright:: 2020- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ARIAMapper = void 0; +var ARIADefinitions_1 = __webpack_require__(/*! ./ARIADefinitions */ "./src/v2/aria/ARIADefinitions.ts"); +var CommonMapper_1 = __webpack_require__(/*! ../common/CommonMapper */ "./src/v2/common/CommonMapper.ts"); +var DOMUtil_1 = __webpack_require__(/*! ../dom/DOMUtil */ "./src/v2/dom/DOMUtil.ts"); +var legacy_1 = __webpack_require__(/*! ../checker/accessibility/util/legacy */ "./src/v2/checker/accessibility/util/legacy.ts"); +var fragment_1 = __webpack_require__(/*! ../checker/accessibility/util/fragment */ "./src/v2/checker/accessibility/util/fragment.ts"); +var ARIAWalker_1 = __webpack_require__(/*! ./ARIAWalker */ "./src/v2/aria/ARIAWalker.ts"); +var CacheUtil_1 = __webpack_require__(/*! ../../v4/util/CacheUtil */ "./src/v4/util/CacheUtil.ts"); +var DOMWalker_1 = __webpack_require__(/*! ../dom/DOMWalker */ "./src/v2/dom/DOMWalker.ts"); +var ARIAMapper = /** @class */ (function (_super) { + __extends(ARIAMapper, _super); + function ARIAMapper() { + return _super !== null && _super.apply(this, arguments) || this; + } + ARIAMapper.prototype.childrenCanHaveRole = function (node, role) { + // if (node.nodeType === 1 /* Node.ELEMENT_NODE */) { + // const elem = node as Element; + // if (elem.getAttribute("aria-hidden") === "true") { + // return false; + // } + // } + return !(role in ARIADefinitions_1.ARIADefinitions.designPatterns && ARIADefinitions_1.ARIADefinitions.designPatterns[role].presentationalChildren); + }; + ARIAMapper.prototype.getRole = function (node) { + var role = ARIAMapper.nodeToRole(node); + return role; + }; + ARIAMapper.prototype.getNamespace = function () { + return "aria"; + }; + ARIAMapper.prototype.getAttributes = function (node) { + var retVal = {}; + if (node.nodeType === 1 /* Node.ELEMENT_NODE */) { + var elem_1 = node; + for (var idx = 0; idx < elem_1.attributes.length; ++idx) { + var attrInfo = elem_1.attributes[idx]; + var name_1 = attrInfo.name.toLowerCase(); + if (name_1.startsWith("aria-")) { + retVal[name_1.substring(5)] = attrInfo.nodeValue; + } + } + var applyAttrRole = function (nodeName) { + if (!(nodeName in ARIAMapper.elemAttrValueCalculators)) + return; + for (var attr in ARIAMapper.elemAttrValueCalculators[nodeName]) { + if (!(attr in retVal)) { + var value = ARIAMapper.elemAttrValueCalculators[nodeName][attr]; + if (typeof value != "undefined" && value !== null) { + if (typeof value !== typeof "") { + value = value(elem_1); + } + retVal[attr] = value; + } + } + } + }; + applyAttrRole("global"); + applyAttrRole(node.nodeName.toLowerCase()); + } + else if (node.nodeType === 3 /* Node.TEXT_NODE */) { + for (var attr in ARIAMapper.textAttrValueCalculators) { + var val = ARIAMapper.textAttrValueCalculators[attr](node); + if (typeof val != "undefined" && val !== null) { + retVal[attr] = val; + } + } + } + return retVal; + }; + ARIAMapper.getAriaOwnedBy = function (elem) { + var doc = fragment_1.FragmentUtil.getOwnerFragment(elem); + if (!(0, CacheUtil_1.getCache)(doc, "ARIAMapper::precalcOwned", false)) { + var owners = doc.querySelectorAll("[aria-owns]"); + for (var iOwner = 0; iOwner < owners.length; ++iOwner) { + var owner = owners[iOwner]; + var ownIds = owner.getAttribute("aria-owns").split(/ +/g); + for (var iId = 0; iId < ownIds.length; ++iId) { + var owned = doc.getElementById(ownIds[iId]); + //ignore if the aria-owns point to the element itself + if (owned && !DOMUtil_1.DOMUtil.sameNode(owner, owned)) { + (0, CacheUtil_1.setCache)(owned, "aria-owned", owner); + } + } + } + (0, CacheUtil_1.setCache)(doc, "ARIAMapper::precalcOwned", true); + } + return (0, CacheUtil_1.getCache)(elem, "aria-owned", null); + }; + ARIAMapper.prototype.getNodeHierarchy = function (node) { + if (!node) + return []; + if (node.nodeType !== 1) { + var parentHierarchy = this.getNodeHierarchy(DOMWalker_1.DOMWalker.parentElement(node)); + var parentInfo = parentHierarchy.length > 0 ? parentHierarchy[parentHierarchy.length - 1] : { + role: "", + rolePath: "", + roleCount: {}, + childrenCanHaveRole: true + }; + var nodeHierarchy = []; + // Set hierarchy + for (var _i = 0, parentHierarchy_1 = parentHierarchy; _i < parentHierarchy_1.length; _i++) { + var item = parentHierarchy_1[_i]; + nodeHierarchy.push(item); + } + nodeHierarchy.push({ + attributes: {}, + bounds: this.getBounds(node), + namespace: this.getNamespace(), + node: node, + role: this.getRole(node) || "none", + rolePath: parentInfo.rolePath + "/" + (this.getRole(node) || "none"), + roleCount: {}, + childrenCanHaveRole: parentInfo.childrenCanHaveRole + }); + return nodeHierarchy; + } + else { + var elem = node; + var nodeHierarchy = (0, CacheUtil_1.getCache)(elem, "ARIAMapper::getNodeHierarchy", null); + if (!nodeHierarchy) { + // This element hasn't been processed yet - but ::reset processes them all in the right order + // Get details about the correct parent first + var parent_1 = ARIAMapper.getAriaOwnedBy(elem); + if (!parent_1) { + parent_1 = DOMWalker_1.DOMWalker.parentElement(elem); + } + while (parent_1 && parent_1.nodeType !== 1) { + parent_1 = DOMWalker_1.DOMWalker.parentElement(elem); + } + var parentHierarchy = parent_1 ? this.getNodeHierarchy(parent_1) : []; + var parentInfo = parentHierarchy.length > 0 ? parentHierarchy[parentHierarchy.length - 1] : { + role: "", + rolePath: "", + roleCount: {}, + childrenCanHaveRole: true + }; + while (parentInfo.role === "none" || parentInfo.role === "/none") { + parent_1 = ARIAMapper.getAriaOwnedBy(parent_1) || DOMWalker_1.DOMWalker.parentElement(parent_1); + parentHierarchy = parent_1 ? this.getNodeHierarchy(parent_1) : []; + parentInfo = parentHierarchy[parentHierarchy.length - 1]; + } + // Set initial node info + var nodeInfo = { + attributes: elem.nodeType === 1 ? this.getAttributes(elem) : {}, + bounds: this.getBounds(elem), + namespace: this.getNamespace(), + node: elem, + role: this.getRole(elem) || "none", + rolePath: "", + roleCount: {}, + childrenCanHaveRole: true + }; + // Adjust role if we're within a presentational container + var presentationalContainer = !parentInfo.childrenCanHaveRole; + if (presentationalContainer) { + nodeInfo.role = "none"; + } + else { + nodeInfo.childrenCanHaveRole = parentInfo.childrenCanHaveRole + && this.childrenCanHaveRole(elem, nodeInfo.role); + } + // Set the paths + if (nodeInfo.role !== "none") { + parentInfo.roleCount[nodeInfo.role] = (parentInfo.roleCount[nodeInfo.role] || 0) + 1; + nodeInfo.rolePath = parentInfo.rolePath + "/" + nodeInfo.role + "[" + parentInfo.roleCount[nodeInfo.role] + "]"; + } + else { + nodeInfo.rolePath = parentInfo.rolePath; + } + // Set hierarchy + nodeHierarchy = []; + for (var _a = 0, parentHierarchy_2 = parentHierarchy; _a < parentHierarchy_2.length; _a++) { + var item = parentHierarchy_2[_a]; + nodeHierarchy.push(item); + } + nodeHierarchy.push(nodeInfo); + (0, CacheUtil_1.setCache)(elem, "ARIAMapper::getNodeHierarchy", nodeHierarchy); + } + return nodeHierarchy; + } + }; + ARIAMapper.prototype.reset = function (node) { + ARIAMapper.nameComputationId = 0; + this.hierarchyRole = []; + this.hierarchyResults = []; + this.hierarchyPath = [{ + rolePath: "", + roleCount: {} + }]; + // Get to the topmost node + var goodNode = node; + var next; + while (next = DOMWalker_1.DOMWalker.parentNode(goodNode)) { + goodNode = next; + } + ; + // Walk the tree and set the hierarchies in the right order + var ariaWalker = new ARIAWalker_1.ARIAWalker(goodNode, false, goodNode); + do { + if (ariaWalker.node.nodeType === 1) { + this.getNodeHierarchy(ariaWalker.node); + } + } while (ariaWalker.nextNode()); + }; + ARIAMapper.prototype.openScope = function (node) { + if (this.hierarchyRole === null) { + this.reset(node); + } + this.pushHierarchy(node); + for (var idx = 0; idx < this.hierarchyResults.length; ++idx) { + if (this.hierarchyResults[idx].role[0] === "/") { + this.hierarchyResults[idx].role = this.hierarchyResults[idx].role.substring(1); + } + } + return this.hierarchyResults; + }; + ARIAMapper.prototype.pushHierarchy = function (node) { + // If we're not an element, no special handling + var nodeHierarchy = []; + // Determine our node info + nodeHierarchy = this.getNodeHierarchy(node); + var nodeInfo = nodeHierarchy[nodeHierarchy.length - 1]; + this.hierarchyRole.push(nodeInfo.role); + if (nodeInfo.role !== "none") { + this.hierarchyPath.push(nodeInfo); + } + this.hierarchyResults = nodeHierarchy; + }; + ARIAMapper.prototype.closeScope = function (node) { + var retVal = []; + for (var _i = 0, _a = this.hierarchyResults; _i < _a.length; _i++) { + var res = _a[_i]; + // const temp = res.node; + // res.node = null; + // let cloned = JSON.parse(JSON.stringify(res)); + // cloned.node = res.node = temp; + // retVal.push(cloned); + retVal.push(res); + } + if (retVal.length > 0) { + retVal[retVal.length - 1].role = "/" + retVal[retVal.length - 1].role; + var parent_2 = DOMWalker_1.DOMWalker.parentElement(node); + this.hierarchyResults = parent_2 ? (0, CacheUtil_1.getCache)(parent_2, "ARIAMapper::getNodeInfo", []) : []; + } + return retVal; + }; + ARIAMapper.computeName = function (cur) { + ++ARIAMapper.nameComputationId; + return ARIAMapper.computeNameHelp(ARIAMapper.nameComputationId, cur, false, false); + }; + ARIAMapper.computeNameHelp = function (walkId, cur, labelledbyTraverse, walkTraverse) { + // 2g. None of the other content applies to text nodes, so just do this first + if (cur.nodeType === 3 /* Node.TEXT_NODE */) + return cur.nodeValue; + if (cur.nodeType === 11) + return ""; + if (cur.nodeType !== 1 /* Node.ELEMENT_NODE */) { + if (walkTraverse || labelledbyTraverse) + return ""; + throw new Error("Can only compute name on Element and Text " + cur.nodeType); + } + var elem = cur; + // We've been here before - prevent recursion + if ((0, CacheUtil_1.getCache)(elem, "data-namewalk", null) === "" + walkId) + return ""; + (0, CacheUtil_1.setCache)(elem, "data-namewalk", "" + walkId); + // See https://www.w3.org/TR/html-aam-1.0/#input-type-text-input-type-password-input-type-search-input-type-tel-input-type-url-and-textarea-element + // 2a. Only show hidden content if it's referenced by a labelledby + if (!labelledbyTraverse && !DOMWalker_1.DOMWalker.isNodeVisible(cur)) { + return ""; + } + // 2b. collect valid id references + if (!labelledbyTraverse && elem.hasAttribute("aria-labelledby")) { + var labelledby = elem.getAttribute("aria-labelledby").split(" "); + var validElems = []; + for (var _i = 0, labelledby_1 = labelledby; _i < labelledby_1.length; _i++) { + var ref = labelledby_1[_i]; + var refElem = fragment_1.FragmentUtil.getById(cur, ref); + if (refElem && !DOMUtil_1.DOMUtil.sameNode(elem, refElem)) { + validElems.push(refElem); + } + } + if (validElems.length > 0) { + var accumulated = ""; + for (var _a = 0, validElems_1 = validElems; _a < validElems_1.length; _a++) { + var elem_2 = validElems_1[_a]; + accumulated += " " + this.computeNameHelp(walkId, elem_2, true, false); + } + return accumulated.trim(); + } + } + // Since nodeToRole calls back here for form and section, we need special casing here to handle those two cases + if (["section", "form"].includes(cur.nodeName.toLowerCase())) { + if (elem.hasAttribute("aria-label") && elem.getAttribute("aria-label").trim().length > 0) { + // If I'm not an embedded control or I'm not recursing, return the aria-label + if (!labelledbyTraverse && !walkTraverse) { + return elem.getAttribute("aria-label").trim(); + } + } + if (elem.hasAttribute("title")) { + return elem.getAttribute("title"); + } + return ""; + } + // 2c. If label or walk, and this is a control, skip to the value, otherwise provide the label + var role = ARIAMapper.nodeToRole(cur); + var isEmbeddedControl = [ + "textbox", "button", "combobox", "listbox", + "progressbar", "scrollbar", "slider", "spinbutton" + ].includes(role); + if (elem.hasAttribute("aria-label") && elem.getAttribute("aria-label").trim().length > 0) { + // If I'm not an embedded control or I'm not recursing, return the aria-label + if (!labelledbyTraverse && !walkTraverse || !isEmbeddedControl) { + return elem.getAttribute("aria-label").trim(); + } + } + // 2d. + if (role !== "presentation" && role !== "none") { + if ((cur.nodeName.toLowerCase() === "img" || cur.nodeName.toLowerCase() === "area") && elem.hasAttribute("alt")) { + return DOMUtil_1.DOMUtil.cleanWhitespace(elem.getAttribute("alt")).trim(); + } + if (cur.nodeName.toLowerCase() === "input" && elem.hasAttribute("id") && elem.getAttribute("id").length > 0) { + var label = elem.ownerDocument.querySelector("label[for='" + elem.getAttribute("id") + "']"); + if (label) { + if (label.hasAttribute("aria-label") || (label.hasAttribute("aria-labelledby") && !legacy_1.RPTUtil.isIdReferToSelf(cur, label.getAttribute("aria-labelledby")))) { + return this.computeNameHelp(walkId, label, false, false); + } + else { + return label.textContent; + } + } + } + if (cur.nodeName.toLowerCase() === "fieldset") { + if (cur.querySelector("legend")) { + var legend = cur.querySelector("legend"); + return legend.innerText; + } + else { + return this.computeNameHelp(walkId, cur, false, false); + } + } + } + // 2e. + if ((walkTraverse || labelledbyTraverse) && isEmbeddedControl) { + // If the embedded control has role textbox, return its value. + if (role === "textbox") { + if (elem.nodeName.toLowerCase() === "input") { + if (elem.hasAttribute("value")) + return elem.getAttribute("value"); + } + else { + walkTraverse = false; + } + } + // If the embedded control has role button, return the text alternative of the button. + if (role === "button") { + if (elem.nodeName.toLowerCase() === "input") { + var type = elem.getAttribute("type").toLowerCase(); + if (["button", "submit", "reset"].includes(type)) { + if (elem.hasAttribute("value")) + return elem.getAttribute("value"); + if (type === "submit") + return "Submit"; + if (type === "reset") + return "Reset"; + } + } + else { + walkTraverse = false; + } + } + // TODO: If the embedded control has role combobox or listbox, return the text alternative of the chosen option. + if (role === "combobox") { + if (elem.hasAttribute("aria-activedescendant")) { + var selected = fragment_1.FragmentUtil.getById(elem, "aria-activedescendant"); + if (selected && !DOMUtil_1.DOMUtil.sameNode(elem, selected)) { + return ARIAMapper.computeNameHelp(walkId, selected, false, false); + } + } + } + // If the embedded control has role range (e.g., a spinbutton or slider): + if (["progressbar", "scrollbar", "slider", "spinbutton"].includes(role)) { + // If the aria-valuetext property is present, return its value, + if (elem.hasAttribute("aria-valuetext")) + return elem.getAttribute("aria-valuetext"); + // Otherwise, if the aria-valuenow property is present, return its value, + if (elem.hasAttribute("aria-valuenow")) + return elem.getAttribute("aria-valuenow"); + // TODO: Otherwise, use the value as specified by a host language attribute. + } + } + // 2f. 2h. + if (walkTraverse || ARIADefinitions_1.ARIADefinitions.nameFromContent(role) || labelledbyTraverse) { + // 2fi. Set the accumulated text to the empty string. + var accumulated = ""; + // 2fii. Check for CSS generated textual content associated with the current node and + // include it in the accumulated text. The CSS :before and :after pseudo elements [CSS2] + // can provide textual content for elements that have a content model. + // For :before pseudo elements, User agents MUST prepend CSS textual content, without + // a space, to the textual content of the current node. + // For :after pseudo elements, User agents MUST append CSS textual content, without a + // space, to the textual content of the current node. + var before = null; + before = elem.ownerDocument.defaultView.getComputedStyle(elem, "before").content; + if (before && before !== "none") { + before = before.replace(/^"/, "").replace(/"$/, ""); + accumulated += before; + } + // 2fiii. For each child node of the current node: + // Set the current node to the child node. + // Compute the text alternative of the current node beginning with step 2. Set the result + // to that text alternative. + // Append the result to the accumulated text. + if (elem.nodeName.toUpperCase() === "SLOT") { + //if no assignedNode, check its own text + if (!elem.assignedNodes() || elem.assignedNodes().length === 0) { + var innerText = legacy_1.RPTUtil.getInnerText(elem); + if (innerText && innerText !== null && innerText.trim().length > 0) + accumulated += " " + innerText; + } + else { + // check text from all assigned nodes + for (var _b = 0, _c = elem.assignedNodes(); _b < _c.length; _b++) { + var slotChild = _c[_b]; + var nextChildContent = ARIAMapper.computeNameHelp(walkId, slotChild, labelledbyTraverse, true); + accumulated += " " + nextChildContent; + } + } + } + else { + var walkChild = elem.firstChild; + while (walkChild) { + var nextChildContent = ARIAMapper.computeNameHelp(walkId, walkChild, labelledbyTraverse, true); + accumulated += " " + nextChildContent; + walkChild = walkChild.nextSibling; + } + } + var after = null; + try { + after = elem.ownerDocument.defaultView.getComputedStyle(elem, "after").content; + } + catch (e) { } + if (after && after !== "none") { + after = after.replace(/^"/, "").replace(/"$/, ""); + accumulated += after; + } + // 2fiv. Return the accumulated text. + accumulated = accumulated.replace(/\s+/g, " ").trim(); + if (accumulated.trim().length > 0) { + return accumulated; + } + } + // 2i. Otherwise, if the current node has a Tooltip attribute, return its value. + if (elem.hasAttribute("title")) { + return elem.getAttribute("title"); + } + if (elem.tagName.toLowerCase() === "svg") { + var title = elem.querySelector("title"); + if (title) { + return title.textContent || title.innerText; + } + } + return ""; + }; + /* if (role in ARIADefinitions.designPatterns + && ARIADefinitions.designPatterns[role].nameFrom + && ARIADefinitions.designPatterns[role].nameFrom.includes("contents")) + { + name = elem.textContent; + } + if (elem.nodeName.toLowerCase() === "input" && elem.hasAttribute("id") && elem.getAttribute("id").trim().length > 0) { + name = elem.ownerDocument.querySelector("label[for='"+elem.getAttribute("id").trim()+"']").textContent; + } + if (elem.hasAttribute("aria-label")) { + name = elem.getAttribute("aria-label"); + } + if (elem.hasAttribute("aria-labelledby")) { + name = ""; + const ids = elem.getAttribute("aria-labelledby").split(" "); + for (const id of ids) { + name += FragmentUtil.getById(elem, id).textContent + " "; + } + name = name.trim(); + } + return name; + }*/ + ARIAMapper.nodeToRole = function (node) { + if (node.nodeType === 3 /* Node.TEXT_NODE */) { + return "text"; + } + else if (node.nodeType !== 1 /* Node.ELEMENT_NODE */) { + return null; + } + var elem = node; + if (!elem || elem.nodeType !== 1 /* Node.ELEMENT_NODE */) { + return null; + } + if (elem.hasAttribute("role") && elem.getAttribute("role").trim().length > 0) { + var roleStr = elem.getAttribute("role").trim(); + var roles_2 = roleStr.split(" "); + for (var _i = 0, roles_1 = roles_2; _i < roles_1.length; _i++) { + var role = roles_1[_i]; + if (role === "presentation" || role === "none") { + // If element is focusable, then presentation roles are to be ignored + if (!legacy_1.RPTUtil.isFocusable(elem)) { + return null; + } + } + else if (role in ARIADefinitions_1.ARIADefinitions.designPatterns) { + return role; + } + } + } + //return this.elemToImplicitRole(elem); + var roles = legacy_1.RPTUtil.getImplicitRole(elem); + return !roles || roles.length === 0 ? null : roles[0]; + }; + //////////////////////////////////////////////////////////////////////////// + // Helper functions + //// + // https://www.w3.org/TR/html-aam-1.0/#mapping-html-to-accessibility-apis + ARIAMapper.elemAttrValueCalculators = { + "global": { + "name": ARIAMapper.computeName + }, + "datalist": { + // set to "true" if the datalist's selection model allows multiple option elements to be + // selected at a time, and "false" otherwise + "multiselectable": function (elem) { + var id = elem.getAttribute("id"); + if (id && id.length > 0) { + var input = elem.ownerDocument.querySelector("input[list='" + id + "']"); + return "" + (elem.getAttribute("multiple") + && (elem.getAttribute("multiple") == "true" || elem.getAttribute("multiple") == "")); + } + return null; + } + }, + "h1": { + "level": "1" + }, + "h2": { + "level": "2" + }, + "h3": { + "level": "3" + }, + "h4": { + "level": "4" + }, + "h5": { + "level": "5" + }, + "h6": { + "level": "6" + }, + "input": { + // - type="checkbox" state set to "mixed" if the element's indeterminate IDL attribute + // is true, or "true" if the element's checkedness is true, or "false" otherwise + // - type="radio" state set to "true" if the element's checkedness is true, or "false" + // otherwise. + "checked": function (elem) { + if (elem.getAttribute("type") === "checkbox" || elem.getAttribute("type") === "radio") { + return "" + elem.checked; + } + return null; + } + // - type="radio" and not in menu reflecting number of type=radio input elements + // within the radio button group + , + "setsize": function (elem) { return null; throw new Error("NOT IMPLEMENTED"); } + // - type="radio" and not in menu value reflecting the elements position + // within the radio button group." + , + "posinset": function (elem) { return null; throw new Error("NOT IMPLEMENTED"); } + // input (type attribute in the Text, Search, Telephone, URL, or E-mail states with a + // suggestions source element) combobox role, with the aria-owns property set to the same + // value as the list attribute + , + "owns": function (elem) { return null; throw new Error("NOT IMPLEMENTED"); } + }, + "keygen": { + "multiselectable": "false" + }, + "li": { + // Number of li elements within the ol, ul, menu + "setsize": function (elem) { + var parent = DOMUtil_1.DOMUtil.getAncestor(elem, ["ol", "ul", "menu"]); + if (!parent) + return null; + var lis = parent.querySelectorAll("li"); + var otherlis = parent.querySelectorAll("ol li, ul li, menu li"); + return "" + (lis.length - otherlis.length); + } + // Position of li element within the ol, ul, menu + , + "posinset": function (elem) { + var parent = DOMUtil_1.DOMUtil.getAncestor(elem, ["ol", "ul", "menu"]); + if (!parent) + return null; + var lis = parent.querySelectorAll("li"); + var num = 0; + for (var idx = 0; idx < lis.length; ++idx) { + var li = lis[idx]; + if (DOMUtil_1.DOMUtil.sameNode(parent, DOMUtil_1.DOMUtil.getAncestor(li, ["ol", "ul", "menu"]))) { + return "" + num; + } + ++num; + } + return null; + } + }, + "menuitem": { + // type = checkbox or radio, set to "true" if the checked attribute + // is present, and "false" otherwise + "checked": function (elem) { return "" + !!(elem.getAttribute("checked") + && (elem.getAttribute("checked") == "true" || elem.getAttribute("checked") == "")); } + }, + "option": { + // set to "true" if the element's selectedness is true, or "false" otherwise. + "selected": function (elem) { return "" + !!(elem.getAttribute("selected") + && (elem.getAttribute("selected") == "true" || elem.getAttribute("selected") == "")); } + }, + "progress": { + "valuemax": function (elem) { return elem.getAttribute("max") || "1"; }, + "valuemin": function (elem) { return "0"; }, + "valuenow": function (elem) { return elem.getAttribute("value"); } + } + }; + ARIAMapper.textAttrValueCalculators = { + "name": function (node) { return node.nodeValue; } + }; + ARIAMapper.nameComputationId = 0; + return ARIAMapper; +}(CommonMapper_1.CommonMapper)); +exports.ARIAMapper = ARIAMapper; + + +/***/ }), + +/***/ "./src/v2/aria/ARIAWalker.ts": +/*!***********************************!*\ + !*** ./src/v2/aria/ARIAWalker.ts ***! + \***********************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + + +/****************************************************************************** + Copyright:: 2020- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ARIAWalker = void 0; +var fragment_1 = __webpack_require__(/*! ../checker/accessibility/util/fragment */ "./src/v2/checker/accessibility/util/fragment.ts"); +var DOMWalker_1 = __webpack_require__(/*! ../dom/DOMWalker */ "./src/v2/dom/DOMWalker.ts"); +var ARIAMapper_1 = __webpack_require__(/*! ./ARIAMapper */ "./src/v2/aria/ARIAMapper.ts"); +/** + * Walks in an ARIA order + * + * See also ../dom/DOMWalker + */ +var ARIAWalker = /** @class */ (function () { + function ARIAWalker(element, bEnd, root) { + this.root = root || element; + this.node = element; + this.bEndTag = (bEnd == undefined ? false : bEnd == true); + } + ARIAWalker.prototype.atRoot = function () { + if (this.ownerElement) + return false; + if (this.root === this.node) { + return true; + } + else if (this.root.isSameNode) { + return this.root.isSameNode(this.node); + } + else if (this.root.compareDocumentPosition) { + return this.root.compareDocumentPosition(this.node) === 0; + } + else { + // Not supported in this environment - try our best + return this.node.parentNode === null; + } + }; + ARIAWalker.prototype.nextNode = function () { + var skipOwned = false; + do { + skipOwned = false; + // console.log(this.node.nodeName, this.bEndTag?"END":"START", this.node.nodeType === 1 && (this.node as any).getAttribute("id")); + if (!this.bEndTag) { + var iframeNode = this.node; + var elementNode = this.node; + var slotElement = this.node; + if (this.node.nodeType === 1 /* Node.ELEMENT_NODE */ + && this.node.nodeName.toUpperCase() === "IFRAME" + && DOMWalker_1.DOMWalker.isNodeVisible(iframeNode) + && iframeNode.contentDocument + && iframeNode.contentDocument.documentElement) { + var ownerElement = this.node; + this.node = iframeNode.contentDocument.documentElement; + this.node.ownerElement = ownerElement; + } + else if (this.node.nodeType === 1 /* Node.ELEMENT_NODE */ + && DOMWalker_1.DOMWalker.isNodeVisible(elementNode) + && elementNode.shadowRoot + && elementNode.shadowRoot.firstChild) { + var ownerElement = this.node; + this.node = elementNode.shadowRoot; + this.node.ownerElement = ownerElement; + } + else if (this.node.nodeType === 1 + && elementNode.nodeName.toLowerCase() === "slot" + && slotElement.assignedNodes().length > 0) { + //TODO: need to conside its own content, a slot may have its own content or assigned content + var slotOwner = this.node; + this.node = slotElement.assignedNodes()[0]; + this.node.slotOwner = slotOwner; + this.node.slotIndex = 0; + } + else if ((this.node.nodeType === 1 /* Node.ELEMENT_NODE */ || this.node.nodeType === 11) /* Node.ELEMENT_NODE */ && this.node.firstChild) { + this.node = this.node.firstChild; + } + else { + this.bEndTag = true; + } + } + else { + if (this.atRoot()) { + return false; + } + else if (this.node.slotOwner) { + var slotOwner = this.node.slotOwner; + var nextSlotIndex = this.node.slotIndex + 1; + delete this.node.slotOwner; + delete this.node.slotIndex; + if (nextSlotIndex < slotOwner.assignedNodes().length) { + this.node = slotOwner.assignedNodes()[nextSlotIndex]; + this.node.slotOwner = slotOwner; + this.node.slotIndex = nextSlotIndex; + this.bEndTag = false; + } + else { + this.node = slotOwner; + this.bEndTag = true; + } + } + else if (this.node.ownerElement) { + this.node = this.node.ownerElement; + this.bEndTag = true; + } + else if (this.node.nextSibling) { + this.node = this.node.nextSibling; + this.bEndTag = false; + skipOwned = true; + } + else if (this.node.parentNode) { + if (this.node.parentNode.nodeType === 1 && this.node.parentNode.hasAttribute("aria-owns")) { + var ownIds = this.node.parentNode.getAttribute("aria-owns").split(/ +/g); + if (this.node.nodeType !== 1 || !this.node.hasAttribute("id")) { + this.node = fragment_1.FragmentUtil.getOwnerFragment(this.node).getElementById(ownIds[0]); + this.bEndTag = false; + } + else { + var idx = ownIds.indexOf(this.node.getAttribute("id")); + if (idx === ownIds.length - 1) { + // last one + this.node = this.node.parentNode; + this.bEndTag = true; + } + else { + // grab next + this.node = fragment_1.FragmentUtil.getOwnerFragment(this.node).getElementById(ownIds[idx + 1]); + this.bEndTag = false; + } + } + } + this.node = this.node.parentNode; + this.bEndTag = true; + } + else { + return false; + } + } + } while ((this.node.nodeType !== 1 /* Node.ELEMENT_NODE */ && this.node.nodeType !== 11 && this.node.nodeType !== 3 /* Node.TEXT_NODE */) + || (this.node.nodeType === 1 && this.node.getAttribute("aChecker") === "ACE") + || (skipOwned && this.node.nodeType === 1 && !!ARIAMapper_1.ARIAMapper.getAriaOwnedBy(this.node))); + return true; + }; + ARIAWalker.prototype.prevNode = function () { + do { + if (this.bEndTag) { + var iframeNode = this.node; + var elementNode = this.node; + if (this.node.nodeType === 1 /* Node.ELEMENT_NODE */ + && this.node.nodeName.toUpperCase() === "IFRAME" + && DOMWalker_1.DOMWalker.isNodeVisible(iframeNode) + && iframeNode.contentDocument + && iframeNode.contentDocument.documentElement) { + var ownerElement = this.node; + this.node = iframeNode.contentDocument.documentElement; + this.node.ownerElement = ownerElement; + } + else if (this.node.nodeType === 1 /* Node.ELEMENT_NODE */ + && DOMWalker_1.DOMWalker.isNodeVisible(elementNode) + && elementNode.shadowRoot + && elementNode.shadowRoot.lastChild) { + var ownerElement = this.node; + this.node = elementNode.shadowRoot; + this.node.ownerElement = ownerElement; + } + else if ((this.node.nodeType === 1 /* Node.ELEMENT_NODE */ || this.node.nodeType === 11) && this.node.lastChild) { + this.node = this.node.lastChild; + } + else { + this.bEndTag = false; + } + } + else { + if (this.atRoot()) { + return false; + } + else if (this.node.previousSibling) { + this.node = this.node.previousSibling; + this.bEndTag = true; + } + else if (this.node.ownerElement) { + this.node = this.node.ownerElement; + this.bEndTag = false; + } + else if (this.node.parentNode) { + this.node = this.node.parentNode; + this.bEndTag = false; + } + else { + return false; + } + } + } while ((this.node.nodeType !== 1 /* Node.ELEMENT_NODE */ && this.node.nodeType !== 11) + || (this.node.nodeType === 1 && this.node.getAttribute("aChecker") === "ACE")); + return true; + }; + return ARIAWalker; +}()); +exports.ARIAWalker = ARIAWalker; + + +/***/ }), + +/***/ "./src/v2/checker/accessibility/util/ancestor.ts": +/*!*******************************************************!*\ + !*** ./src/v2/checker/accessibility/util/ancestor.ts ***! + \*******************************************************/ +/***/ ((__unused_webpack_module, exports) => { + + +/****************************************************************************** + Copyright:: 2020- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AncestorUtil = void 0; +var AncestorUtil = /** @class */ (function () { + function AncestorUtil() { + } + AncestorUtil.isPresentationFrame = function (contextHierarchy) { + if (contextHierarchy && contextHierarchy.dom) { + // Skip current node because we want ancestry + for (var idx = contextHierarchy.dom.length - 2; idx >= 0; --idx) { + var elem = contextHierarchy.dom[idx].node; + if (elem.nodeType === 1 + && elem.nodeName.toLowerCase() === "iframe" + && (elem.getAttribute("role") === "presentation" || elem.getAttribute("aria-hidden") === "true")) { + return true; + } + } + } + return false; + }; + AncestorUtil.isFrame = function (contextHierarchy) { + if (contextHierarchy && contextHierarchy.dom) { + // Skip current node because we want ancestry + for (var idx = contextHierarchy.dom.length - 2; idx >= 0; --idx) { + var elem = contextHierarchy.dom[idx].node; + if (elem.nodeType === 1 && elem.nodeName.toLowerCase() === "iframe") { + return true; + } + } + } + return false; + }; + return AncestorUtil; +}()); +exports.AncestorUtil = AncestorUtil; + + +/***/ }), + +/***/ "./src/v2/checker/accessibility/util/fragment.ts": +/*!*******************************************************!*\ + !*** ./src/v2/checker/accessibility/util/fragment.ts ***! + \*******************************************************/ +/***/ ((__unused_webpack_module, exports) => { + + +/****************************************************************************** + Copyright:: 2020- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.FragmentUtil = void 0; +var FragmentUtil = /** @class */ (function () { + function FragmentUtil() { + } + FragmentUtil.getOwnerFragment = function (node) { + var n = node; + while (n.parentNode && (n = n.parentNode)) { + if (n.nodeType === 11) { + return n; + } + } + return node.ownerDocument; + }; + FragmentUtil.getById = function (node, id) { + return this.getOwnerFragment(node).getElementById(id); + }; + FragmentUtil.getAncestor = function (hierarchies, elemName) { + var matches = hierarchies["dom"].filter(function (info) { return info.role === elemName; }); + return matches.length > 0 && matches[0].node || null; + }; + FragmentUtil.getAncestorWithRole = function (hierarchies, role) { + var matches = hierarchies["aria"].filter(function (info) { return info.role === role; }); + return matches.length > 0 && matches[0].node || null; + }; + return FragmentUtil; +}()); +exports.FragmentUtil = FragmentUtil; + + +/***/ }), + +/***/ "./src/v2/checker/accessibility/util/lang.ts": +/*!***************************************************!*\ + !*** ./src/v2/checker/accessibility/util/lang.ts ***! + \***************************************************/ +/***/ ((__unused_webpack_module, exports) => { + + +/****************************************************************************** + Copyright:: 2021- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.LangUtil = void 0; +// From https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry +var validPrimaryLangs = [ + ["aa", "ab", "ae", "af", "ak", "am", "an", "ar", "as", "av", "ay", "az", "aaa", "aab", "aac", "aad", "aae", "aaf", "aag", "aah", "aai", "aak", "aal", "aam", "aan", "aao", "aap", "aaq", "aas", "aat", "aau", "aav", "aaw", "aax", "aaz", "aba", "abb", "abc", "abd", "abe", "abf", "abg", "abh", "abi", "abj", "abl", "abm", "abn", "abo", "abp", "abq", "abr", "abs", "abt", "abu", "abv", "abw", "abx", "aby", "abz", "aca", "acb", "acd", "ace", "acf", "ach", "aci", "ack", "acl", "acm", "acn", "acp", "acq", "acr", "acs", "act", "acu", "acv", "acw", "acx", "acy", "acz", "ada", "adb", "add", "ade", "adf", "adg", "adh", "adi", "adj", "adl", "adn", "ado", "adp", "adq", "adr", "ads", "adt", "adu", "adw", "adx", "ady", "adz", "aea", "aeb", "aec", "aed", "aee", "aek", "ael", "aem", "aen", "aeq", "aer", "aes", "aeu", "aew", "aey", "aez", "afa", "afb", "afd", "afe", "afg", "afh", "afi", "afk", "afn", "afo", "afp", "afs", "aft", "afu", "afz", "aga", "agb", "agc", "agd", "age", "agf", "agg", "agh", "agi", "agj", "agk", "agl", "agm", "agn", "ago", "agp", "agq", "agr", "ags", "agt", "agu", "agv", "agw", "agx", "agy", "agz", "aha", "ahb", "ahg", "ahh", "ahi", "ahk", "ahl", "ahm", "ahn", "aho", "ahp", "ahr", "ahs", "aht", "aia", "aib", "aic", "aid", "aie", "aif", "aig", "aih", "aii", "aij", "aik", "ail", "aim", "ain", "aio", "aip", "aiq", "air", "ais", "ait", "aiw", "aix", "aiy", "aja", "ajg", "aji", "ajn", "ajp", "ajt", "aju", "ajw", "ajz", "akb", "akc", "akd", "ake", "akf", "akg", "akh", "aki", "akj", "akk", "akl", "akm", "ako", "akp", "akq", "akr", "aks", "akt", "aku", "akv", "akw", "akx", "aky", "akz", "ala", "alc", "ald", "ale", "alf", "alg", "alh", "ali", "alj", "alk", "all", "alm", "aln", "alo", "alp", "alq", "alr", "als", "alt", "alu", "alv", "alw", "alx", "aly", "alz", "ama", "amb", "amc", "ame", "amf", "amg", "ami", "amj", "amk", "aml", "amm", "amn", "amo", "amp", "amq", "amr", "ams", "amt", "amu", "amv", "amw", "amx", "amy", "amz", "ana", "anb", "anc", "and", "ane", "anf", "ang", "anh", "ani", "anj", "ank", "anl", "anm", "ann", "ano", "anp", "anq", "anr", "ans", "ant", "anu", "anv", "anw", "anx", "any", "anz", "aoa", "aob", "aoc", "aod", "aoe", "aof", "aog", "aoh", "aoi", "aoj", "aok", "aol", "aom", "aon", "aor", "aos", "aot", "aou", "aox", "aoz", "apa", "apb", "apc", "apd", "ape", "apf", "apg", "aph", "api", "apj", "apk", "apl", "apm", "apn", "apo", "app", "apq", "apr", "aps", "apt", "apu", "apv", "apw", "apx", "apy", "apz", "aqa", "aqc", "aqd", "aqg", "aqk", "aql", "aqm", "aqn", "aqp", "aqr", "aqt", "aqz", "arb", "arc", "ard", "are", "arh", "ari", "arj", "ark", "arl", "arn", "aro", "arp", "arq", "arr", "ars", "art", "aru", "arv", "arw", "arx", "ary", "arz", "asa", "asb", "asc", "asd", "ase", "asf", "asg", "ash", "asi", "asj", "ask", "asl", "asn", "aso", "asp", "asq", "asr", "ass", "ast", "asu", "asv", "asw", "asx", "asy", "asz", "ata", "atb", "atc", "atd", "ate", "atg", "ath", "ati", "atj", "atk", "atl", "atm", "atn", "ato", "atp", "atq", "atr", "ats", "att", "atu", "atv", "atw", "atx", "aty", "atz", "aua", "aub", "auc", "aud", "aue", "auf", "aug", "auh", "aui", "auj", "auk", "aul", "aum", "aun", "auo", "aup", "auq", "aur", "aus", "aut", "auu", "auw", "aux", "auy", "auz", "avb", "avd", "avi", "avk", "avl", "avm", "avn", "avo", "avs", "avt", "avu", "avv", "awa", "awb", "awc", "awd", "awe", "awg", "awh", "awi", "awk", "awm", "awn", "awo", "awr", "aws", "awt", "awu", "awv", "aww", "awx", "awy", "axb", "axe", "axg", "axk", "axl", "axm", "axx", "aya", "ayb", "ayc", "ayd", "aye", "ayg", "ayh", "ayi", "ayk", "ayl", "ayn", "ayo", "ayp", "ayq", "ayr", "ays", "ayt", "ayu", "ayx", "ayy", "ayz", "aza", "azb", "azc", "azd", "azg", "azj", "azm", "azn", "azo", "azt", "azz"], + ["ba", "be", "bg", "bh", "bi", "bm", "bn", "bo", "br", "bs", "baa", "bab", "bac", "bad", "bae", "baf", "bag", "bah", "bai", "baj", "bal", "ban", "bao", "bap", "bar", "bas", "bat", "bau", "bav", "baw", "bax", "bay", "baz", "bba", "bbb", "bbc", "bbd", "bbe", "bbf", "bbg", "bbh", "bbi", "bbj", "bbk", "bbl", "bbm", "bbn", "bbo", "bbp", "bbq", "bbr", "bbs", "bbt", "bbu", "bbv", "bbw", "bbx", "bby", "bbz", "bca", "bcb", "bcc", "bcd", "bce", "bcf", "bcg", "bch", "bci", "bcj", "bck", "bcl", "bcm", "bcn", "bco", "bcp", "bcq", "bcr", "bcs", "bct", "bcu", "bcv", "bcw", "bcy", "bcz", "bda", "bdb", "bdc", "bdd", "bde", "bdf", "bdg", "bdh", "bdi", "bdj", "bdk", "bdl", "bdm", "bdn", "bdo", "bdp", "bdq", "bdr", "bds", "bdt", "bdu", "bdv", "bdw", "bdx", "bdy", "bdz", "bea", "beb", "bec", "bed", "bee", "bef", "beg", "beh", "bei", "bej", "bek", "bem", "beo", "bep", "beq", "ber", "bes", "bet", "beu", "bev", "bew", "bex", "bey", "bez", "bfa", "bfb", "bfc", "bfd", "bfe", "bff", "bfg", "bfh", "bfi", "bfj", "bfk", "bfl", "bfm", "bfn", "bfo", "bfp", "bfq", "bfr", "bfs", "bft", "bfu", "bfw", "bfx", "bfy", "bfz", "bga", "bgb", "bgc", "bgd", "bge", "bgf", "bgg", "bgi", "bgj", "bgk", "bgl", "bgm", "bgn", "bgo", "bgp", "bgq", "bgr", "bgs", "bgt", "bgu", "bgv", "bgw", "bgx", "bgy", "bgz", "bha", "bhb", "bhc", "bhd", "bhe", "bhf", "bhg", "bhh", "bhi", "bhj", "bhk", "bhl", "bhm", "bhn", "bho", "bhp", "bhq", "bhr", "bhs", "bht", "bhu", "bhv", "bhw", "bhx", "bhy", "bhz", "bia", "bib", "bic", "bid", "bie", "bif", "big", "bij", "bik", "bil", "bim", "bin", "bio", "bip", "biq", "bir", "bit", "biu", "biv", "biw", "bix", "biy", "biz", "bja", "bjb", "bjc", "bjd", "bje", "bjf", "bjg", "bjh", "bji", "bjj", "bjk", "bjl", "bjm", "bjn", "bjo", "bjp", "bjq", "bjr", "bjs", "bjt", "bju", "bjv", "bjw", "bjx", "bjy", "bjz", "bka", "bkb", "bkc", "bkd", "bkf", "bkg", "bkh", "bki", "bkj", "bkk", "bkl", "bkm", "bkn", "bko", "bkp", "bkq", "bkr", "bks", "bkt", "bku", "bkv", "bkw", "bkx", "bky", "bkz", "bla", "blb", "blc", "bld", "ble", "blf", "blg", "blh", "bli", "blj", "blk", "bll", "blm", "bln", "blo", "blp", "blq", "blr", "bls", "blt", "blv", "blw", "blx", "bly", "blz", "bma", "bmb", "bmc", "bmd", "bme", "bmf", "bmg", "bmh", "bmi", "bmj", "bmk", "bml", "bmm", "bmn", "bmo", "bmp", "bmq", "bmr", "bms", "bmt", "bmu", "bmv", "bmw", "bmx", "bmy", "bmz", "bna", "bnb", "bnc", "bnd", "bne", "bnf", "bng", "bni", "bnj", "bnk", "bnl", "bnm", "bnn", "bno", "bnp", "bnq", "bnr", "bns", "bnt", "bnu", "bnv", "bnw", "bnx", "bny", "bnz", "boa", "bob", "boe", "bof", "bog", "boh", "boi", "boj", "bok", "bol", "bom", "bon", "boo", "bop", "boq", "bor", "bot", "bou", "bov", "bow", "box", "boy", "boz", "bpa", "bpb", "bpd", "bpe", "bpg", "bph", "bpi", "bpj", "bpk", "bpl", "bpm", "bpn", "bpo", "bpp", "bpq", "bpr", "bps", "bpt", "bpu", "bpv", "bpw", "bpx", "bpy", "bpz", "bqa", "bqb", "bqc", "bqd", "bqf", "bqg", "bqh", "bqi", "bqj", "bqk", "bql", "bqm", "bqn", "bqo", "bqp", "bqq", "bqr", "bqs", "bqt", "bqu", "bqv", "bqw", "bqx", "bqy", "bqz", "bra", "brb", "brc", "brd", "brf", "brg", "brh", "bri", "brj", "brk", "brl", "brm", "brn", "bro", "brp", "brq", "brr", "brs", "brt", "bru", "brv", "brw", "brx", "bry", "brz", "bsa", "bsb", "bsc", "bse", "bsf", "bsg", "bsh", "bsi", "bsj", "bsk", "bsl", "bsm", "bsn", "bso", "bsp", "bsq", "bsr", "bss", "bst", "bsu", "bsv", "bsw", "bsx", "bsy", "bta", "btb", "btc", "btd", "bte", "btf", "btg", "bth", "bti", "btj", "btk", "btl", "btm", "btn", "bto", "btp", "btq", "btr", "bts", "btt", "btu", "btv", "btw", "btx", "bty", "btz", "bua", "bub", "buc", "bud", "bue", "buf", "bug", "buh", "bui", "buj", "buk", "bum", "bun", "buo", "bup", "buq", "bus", "but", "buu", "buv", "buw", "bux", "buy", "buz", "bva", "bvb", "bvc", "bvd", "bve", "bvf", "bvg", "bvh", "bvi", "bvj", "bvk", "bvl", "bvm", "bvn", "bvo", "bvp", "bvq", "bvr", "bvt", "bvu", "bvv", "bvw", "bvx", "bvy", "bvz", "bwa", "bwb", "bwc", "bwd", "bwe", "bwf", "bwg", "bwh", "bwi", "bwj", "bwk", "bwl", "bwm", "bwn", "bwo", "bwp", "bwq", "bwr", "bws", "bwt", "bwu", "bww", "bwx", "bwy", "bwz", "bxa", "bxb", "bxc", "bxd", "bxe", "bxf", "bxg", "bxh", "bxi", "bxj", "bxk", "bxl", "bxm", "bxn", "bxo", "bxp", "bxq", "bxr", "bxs", "bxu", "bxv", "bxw", "bxx", "bxz", "bya", "byb", "byc", "byd", "bye", "byf", "byg", "byh", "byi", "byj", "byk", "byl", "bym", "byn", "byo", "byp", "byq", "byr", "bys", "byt", "byv", "byw", "byx", "byy", "byz", "bza", "bzb", "bzc", "bzd", "bze", "bzf", "bzg", "bzh", "bzi", "bzj", "bzk", "bzl", "bzm", "bzn", "bzo", "bzp", "bzq", "bzr", "bzs", "bzt", "bzu", "bzv", "bzw", "bzx", "bzy", "bzz"], + ["ca", "ce", "ch", "co", "cr", "cs", "cu", "cv", "cy", "caa", "cab", "cac", "cad", "cae", "caf", "cag", "cah", "cai", "caj", "cak", "cal", "cam", "can", "cao", "cap", "caq", "car", "cas", "cau", "cav", "caw", "cax", "cay", "caz", "cba", "cbb", "cbc", "cbd", "cbe", "cbg", "cbh", "cbi", "cbj", "cbk", "cbl", "cbn", "cbo", "cbq", "cbr", "cbs", "cbt", "cbu", "cbv", "cbw", "cby", "cca", "ccc", "ccd", "cce", "ccg", "cch", "ccj", "ccl", "ccm", "ccn", "cco", "ccp", "ccq", "ccr", "ccs", "cda", "cdc", "cdd", "cde", "cdf", "cdg", "cdh", "cdi", "cdj", "cdm", "cdn", "cdo", "cdr", "cds", "cdy", "cdz", "cea", "ceb", "ceg", "cek", "cel", "cen", "cet", "cey", "cfa", "cfd", "cfg", "cfm", "cga", "cgc", "cgg", "cgk", "chb", "chc", "chd", "chf", "chg", "chh", "chj", "chk", "chl", "chm", "chn", "cho", "chp", "chq", "chr", "cht", "chw", "chx", "chy", "chz", "cia", "cib", "cic", "cid", "cie", "cih", "cik", "cim", "cin", "cip", "cir", "ciw", "ciy", "cja", "cje", "cjh", "cji", "cjk", "cjm", "cjn", "cjo", "cjp", "cjr", "cjs", "cjv", "cjy", "cka", "ckb", "ckh", "ckl", "ckm", "ckn", "cko", "ckq", "ckr", "cks", "ckt", "cku", "ckv", "ckx", "cky", "ckz", "cla", "clc", "cld", "cle", "clh", "cli", "clj", "clk", "cll", "clm", "clo", "clt", "clu", "clw", "cly", "cma", "cmc", "cme", "cmg", "cmi", "cmk", "cml", "cmm", "cmn", "cmo", "cmr", "cms", "cmt", "cna", "cnb", "cnc", "cng", "cnh", "cni", "cnk", "cnl", "cno", "cnp", "cnr", "cns", "cnt", "cnu", "cnw", "cnx", "coa", "cob", "coc", "cod", "coe", "cof", "cog", "coh", "coj", "cok", "col", "com", "con", "coo", "cop", "coq", "cot", "cou", "cov", "cow", "cox", "coy", "coz", "cpa", "cpb", "cpc", "cpe", "cpf", "cpg", "cpi", "cpn", "cpo", "cpp", "cps", "cpu", "cpx", "cpy", "cqd", "cqu", "cra", "crb", "crc", "crd", "crf", "crg", "crh", "cri", "crj", "crk", "crl", "crm", "crn", "cro", "crp", "crq", "crr", "crs", "crt", "crv", "crw", "crx", "cry", "crz", "csa", "csb", "csc", "csd", "cse", "csf", "csg", "csh", "csi", "csj", "csk", "csl", "csm", "csn", "cso", "csp", "csq", "csr", "css", "cst", "csu", "csv", "csw", "csx", "csy", "csz", "cta", "ctc", "ctd", "cte", "ctg", "cth", "ctl", "ctm", "ctn", "cto", "ctp", "cts", "ctt", "ctu", "cty", "ctz", "cua", "cub", "cuc", "cug", "cuh", "cui", "cuj", "cuk", "cul", "cum", "cuo", "cup", "cuq", "cur", "cus", "cut", "cuu", "cuv", "cuw", "cux", "cuy", "cvg", "cvn", "cwa", "cwb", "cwd", "cwe", "cwg", "cwt", "cya", "cyb", "cyo", "czh", "czk", "czn", "czo", "czt"], + ["da", "de", "dv", "dz", "daa", "dac", "dad", "dae", "daf", "dag", "dah", "dai", "daj", "dak", "dal", "dam", "dao", "dap", "daq", "dar", "das", "dau", "dav", "daw", "dax", "day", "daz", "dba", "dbb", "dbd", "dbe", "dbf", "dbg", "dbi", "dbj", "dbl", "dbm", "dbn", "dbo", "dbp", "dbq", "dbr", "dbt", "dbu", "dbv", "dbw", "dby", "dcc", "dcr", "dda", "ddd", "dde", "ddg", "ddi", "ddj", "ddn", "ddo", "ddr", "dds", "ddw", "dec", "ded", "dee", "def", "deg", "deh", "dei", "dek", "del", "dem", "den", "dep", "deq", "der", "des", "dev", "dez", "dga", "dgb", "dgc", "dgd", "dge", "dgg", "dgh", "dgi", "dgk", "dgl", "dgn", "dgo", "dgr", "dgs", "dgt", "dgu", "dgw", "dgx", "dgz", "dha", "dhd", "dhg", "dhi", "dhl", "dhm", "dhn", "dho", "dhr", "dhs", "dhu", "dhv", "dhw", "dhx", "dia", "dib", "dic", "did", "dif", "dig", "dih", "dii", "dij", "dik", "dil", "dim", "din", "dio", "dip", "diq", "dir", "dis", "dit", "diu", "diw", "dix", "diy", "diz", "dja", "djb", "djc", "djd", "dje", "djf", "dji", "djj", "djk", "djl", "djm", "djn", "djo", "djr", "dju", "djw", "dka", "dkg", "dkk", "dkl", "dkr", "dks", "dkx", "dlg", "dlk", "dlm", "dln", "dma", "dmb", "dmc", "dmd", "dme", "dmf", "dmg", "dmk", "dml", "dmm", "dmn", "dmo", "dmr", "dms", "dmu", "dmv", "dmw", "dmx", "dmy", "dna", "dnd", "dne", "dng", "dni", "dnj", "dnk", "dnn", "dno", "dnr", "dnt", "dnu", "dnv", "dnw", "dny", "doa", "dob", "doc", "doe", "dof", "doh", "doi", "dok", "dol", "don", "doo", "dop", "doq", "dor", "dos", "dot", "dov", "dow", "dox", "doy", "doz", "dpp", "dra", "drb", "drc", "drd", "dre", "drg", "drh", "dri", "drl", "drn", "dro", "drq", "drr", "drs", "drt", "dru", "drw", "dry", "dsb", "dse", "dsh", "dsi", "dsl", "dsn", "dso", "dsq", "dta", "dtb", "dtd", "dth", "dti", "dtk", "dtm", "dtn", "dto", "dtp", "dtr", "dts", "dtt", "dtu", "dty", "dua", "dub", "duc", "dud", "due", "duf", "dug", "duh", "dui", "duj", "duk", "dul", "dum", "dun", "duo", "dup", "duq", "dur", "dus", "duu", "duv", "duw", "dux", "duy", "duz", "dva", "dwa", "dwk", "dwl", "dwr", "dws", "dwu", "dww", "dwy", "dwz", "dya", "dyb", "dyd", "dyg", "dyi", "dym", "dyn", "dyo", "dyu", "dyy", "dza", "dzd", "dze", "dzg", "dzl", "dzn"], + ["ee", "el", "en", "eo", "es", "et", "eu", "eaa", "ebc", "ebg", "ebk", "ebo", "ebr", "ebu", "ecr", "ecs", "ecy", "eee", "efa", "efe", "efi", "ega", "egl", "ego", "egx", "egy", "ehs", "ehu", "eip", "eit", "eiv", "eja", "eka", "ekc", "eke", "ekg", "eki", "ekk", "ekl", "ekm", "eko", "ekp", "ekr", "eky", "ele", "elh", "eli", "elk", "elm", "elo", "elp", "elu", "elx", "ema", "emb", "eme", "emg", "emi", "emk", "emm", "emn", "emo", "emp", "emq", "ems", "emu", "emw", "emx", "emy", "emz", "ena", "enb", "enc", "end", "enf", "enh", "enl", "enm", "enn", "eno", "enq", "enr", "enu", "env", "enw", "enx", "eot", "epi", "era", "erg", "erh", "eri", "erk", "ero", "err", "ers", "ert", "erw", "ese", "esg", "esh", "esi", "esk", "esl", "esm", "esn", "eso", "esq", "ess", "esu", "esx", "esy", "etb", "etc", "eth", "etn", "eto", "etr", "ets", "ett", "etu", "etx", "etz", "euq", "eve", "evh", "evn", "ewo", "ext", "eya", "eyo", "eza", "eze"], + ["fa", "ff", "fi", "fj", "fo", "fr", "fy", "faa", "fab", "fad", "faf", "fag", "fah", "fai", "faj", "fak", "fal", "fam", "fan", "fap", "far", "fat", "fau", "fax", "fay", "faz", "fbl", "fcs", "fer", "ffi", "ffm", "fgr", "fia", "fie", "fif", "fil", "fip", "fir", "fit", "fiu", "fiw", "fkk", "fkv", "fla", "flh", "fli", "fll", "fln", "flr", "fly", "fmp", "fmu", "fnb", "fng", "fni", "fod", "foi", "fom", "fon", "for", "fos", "fox", "fpe", "fqs", "frc", "frd", "frk", "frm", "fro", "frp", "frq", "frr", "frs", "frt", "fse", "fsl", "fss", "fub", "fuc", "fud", "fue", "fuf", "fuh", "fui", "fuj", "fum", "fun", "fuq", "fur", "fut", "fuu", "fuv", "fuy", "fvr", "fwa", "fwe"], + ["ga", "gd", "gl", "gn", "gu", "gv", "gaa", "gab", "gac", "gad", "gae", "gaf", "gag", "gah", "gai", "gaj", "gak", "gal", "gam", "gan", "gao", "gap", "gaq", "gar", "gas", "gat", "gau", "gav", "gaw", "gax", "gay", "gaz", "gba", "gbb", "gbc", "gbd", "gbe", "gbf", "gbg", "gbh", "gbi", "gbj", "gbk", "gbl", "gbm", "gbn", "gbo", "gbp", "gbq", "gbr", "gbs", "gbu", "gbv", "gbw", "gbx", "gby", "gbz", "gcc", "gcd", "gce", "gcf", "gcl", "gcn", "gcr", "gct", "gda", "gdb", "gdc", "gdd", "gde", "gdf", "gdg", "gdh", "gdi", "gdj", "gdk", "gdl", "gdm", "gdn", "gdo", "gdq", "gdr", "gds", "gdt", "gdu", "gdx", "gea", "geb", "gec", "ged", "gef", "geg", "geh", "gei", "gej", "gek", "gel", "gem", "geq", "ges", "gev", "gew", "gex", "gey", "gez", "gfk", "gft", "gfx", "gga", "ggb", "ggd", "gge", "ggg", "ggk", "ggl", "ggn", "ggo", "ggr", "ggt", "ggu", "ggw", "gha", "ghc", "ghe", "ghh", "ghk", "ghl", "ghn", "gho", "ghr", "ghs", "ght", "gia", "gib", "gic", "gid", "gie", "gig", "gih", "gii", "gil", "gim", "gin", "gio", "gip", "giq", "gir", "gis", "git", "giu", "giw", "gix", "giy", "giz", "gji", "gjk", "gjm", "gjn", "gjr", "gju", "gka", "gkd", "gke", "gkn", "gko", "gkp", "gku", "glb", "glc", "gld", "glh", "gli", "glj", "glk", "gll", "glo", "glr", "glu", "glw", "gly", "gma", "gmb", "gmd", "gme", "gmg", "gmh", "gml", "gmm", "gmn", "gmq", "gmr", "gmu", "gmv", "gmw", "gmx", "gmy", "gmz", "gna", "gnb", "gnc", "gnd", "gne", "gng", "gnh", "gni", "gnj", "gnk", "gnl", "gnm", "gnn", "gno", "gnq", "gnr", "gnt", "gnu", "gnw", "gnz", "goa", "gob", "goc", "god", "goe", "gof", "gog", "goh", "goi", "goj", "gok", "gol", "gom", "gon", "goo", "gop", "goq", "gor", "gos", "got", "gou", "gow", "gox", "goy", "goz", "gpa", "gpe", "gpn", "gqa", "gqi", "gqn", "gqr", "gqu", "gra", "grb", "grc", "grd", "grg", "grh", "gri", "grj", "grk", "grm", "gro", "grq", "grr", "grs", "grt", "gru", "grv", "grw", "grx", "gry", "grz", "gse", "gsg", "gsl", "gsm", "gsn", "gso", "gsp", "gss", "gsw", "gta", "gti", "gtu", "gua", "gub", "guc", "gud", "gue", "guf", "gug", "guh", "gui", "guk", "gul", "gum", "gun", "guo", "gup", "guq", "gur", "gus", "gut", "guu", "guv", "guw", "gux", "guz", "gva", "gvc", "gve", "gvf", "gvj", "gvl", "gvm", "gvn", "gvo", "gvp", "gvr", "gvs", "gvy", "gwa", "gwb", "gwc", "gwd", "gwe", "gwf", "gwg", "gwi", "gwj", "gwm", "gwn", "gwr", "gwt", "gwu", "gww", "gwx", "gxx", "gya", "gyb", "gyd", "gye", "gyf", "gyg", "gyi", "gyl", "gym", "gyn", "gyo", "gyr", "gyy", "gyz", "gza", "gzi", "gzn"], + ["ha", "he", "hi", "ho", "hr", "ht", "hu", "hy", "hz", "haa", "hab", "hac", "had", "hae", "haf", "hag", "hah", "hai", "haj", "hak", "hal", "ham", "han", "hao", "hap", "haq", "har", "has", "hav", "haw", "hax", "hay", "haz", "hba", "hbb", "hbn", "hbo", "hbu", "hca", "hch", "hdn", "hds", "hdy", "hea", "hed", "heg", "heh", "hei", "hem", "hgm", "hgw", "hhi", "hhr", "hhy", "hia", "hib", "hid", "hif", "hig", "hih", "hii", "hij", "hik", "hil", "him", "hio", "hir", "hit", "hiw", "hix", "hji", "hka", "hke", "hkh", "hkk", "hkn", "hks", "hla", "hlb", "hld", "hle", "hlt", "hlu", "hma", "hmb", "hmc", "hmd", "hme", "hmf", "hmg", "hmh", "hmi", "hmj", "hmk", "hml", "hmm", "hmn", "hmp", "hmq", "hmr", "hms", "hmt", "hmu", "hmv", "hmw", "hmx", "hmy", "hmz", "hna", "hnd", "hne", "hng", "hnh", "hni", "hnj", "hnn", "hno", "hns", "hnu", "hoa", "hob", "hoc", "hod", "hoe", "hoh", "hoi", "hoj", "hok", "hol", "hom", "hoo", "hop", "hor", "hos", "hot", "hov", "how", "hoy", "hoz", "hpo", "hps", "hra", "hrc", "hre", "hrk", "hrm", "hro", "hrp", "hrr", "hrt", "hru", "hrw", "hrx", "hrz", "hsb", "hsh", "hsl", "hsn", "hss", "hti", "hto", "hts", "htu", "htx", "hub", "huc", "hud", "hue", "huf", "hug", "huh", "hui", "huj", "huk", "hul", "hum", "huo", "hup", "huq", "hur", "hus", "hut", "huu", "huv", "huw", "hux", "huy", "huz", "hvc", "hve", "hvk", "hvn", "hvv", "hwa", "hwc", "hwo", "hya", "hyw", "hyx"], + ["ia", "id", "ie", "ig", "ii", "ik", "in", "io", "is", "it", "iu", "iw", "iai", "ian", "iap", "iar", "iba", "ibb", "ibd", "ibe", "ibg", "ibh", "ibi", "ibl", "ibm", "ibn", "ibr", "ibu", "iby", "ica", "ich", "icl", "icr", "ida", "idb", "idc", "idd", "ide", "idi", "idr", "ids", "idt", "idu", "ifa", "ifb", "ife", "iff", "ifk", "ifm", "ifu", "ify", "igb", "ige", "igg", "igl", "igm", "ign", "igo", "igs", "igw", "ihb", "ihi", "ihp", "ihw", "iin", "iir", "ijc", "ije", "ijj", "ijn", "ijo", "ijs", "ike", "iki", "ikk", "ikl", "iko", "ikp", "ikr", "iks", "ikt", "ikv", "ikw", "ikx", "ikz", "ila", "ilb", "ilg", "ili", "ilk", "ill", "ilm", "ilo", "ilp", "ils", "ilu", "ilv", "ilw", "ima", "ime", "imi", "iml", "imn", "imo", "imr", "ims", "imy", "inb", "inc", "ine", "ing", "inh", "inj", "inl", "inm", "inn", "ino", "inp", "ins", "int", "inz", "ior", "iou", "iow", "ipi", "ipo", "iqu", "iqw", "ira", "ire", "irh", "iri", "irk", "irn", "iro", "irr", "iru", "irx", "iry", "isa", "isc", "isd", "ise", "isg", "ish", "isi", "isk", "ism", "isn", "iso", "isr", "ist", "isu", "itb", "itc", "itd", "ite", "iti", "itk", "itl", "itm", "ito", "itr", "its", "itt", "itv", "itw", "itx", "ity", "itz", "ium", "ivb", "ivv", "iwk", "iwm", "iwo", "iws", "ixc", "ixl", "iya", "iyo", "iyx", "izh", "izi", "izr", "izz"], + ["ja", "ji", "jv", "jw", "jaa", "jab", "jac", "jad", "jae", "jaf", "jah", "jaj", "jak", "jal", "jam", "jan", "jao", "jaq", "jar", "jas", "jat", "jau", "jax", "jay", "jaz", "jbe", "jbi", "jbj", "jbk", "jbm", "jbn", "jbo", "jbr", "jbt", "jbu", "jbw", "jcs", "jct", "jda", "jdg", "jdt", "jeb", "jee", "jeg", "jeh", "jei", "jek", "jel", "jen", "jer", "jet", "jeu", "jgb", "jge", "jgk", "jgo", "jhi", "jhs", "jia", "jib", "jic", "jid", "jie", "jig", "jih", "jii", "jil", "jim", "jio", "jiq", "jit", "jiu", "jiv", "jiy", "jje", "jjr", "jka", "jkm", "jko", "jkp", "jkr", "jks", "jku", "jle", "jls", "jma", "jmb", "jmc", "jmd", "jmi", "jml", "jmn", "jmr", "jms", "jmw", "jmx", "jna", "jnd", "jng", "jni", "jnj", "jnl", "jns", "job", "jod", "jog", "jor", "jos", "jow", "jpa", "jpr", "jpx", "jqr", "jra", "jrb", "jrr", "jrt", "jru", "jsl", "jua", "jub", "juc", "jud", "juh", "jui", "juk", "jul", "jum", "jun", "juo", "jup", "jur", "jus", "jut", "juu", "juw", "juy", "jvd", "jvn", "jwi", "jya", "jye", "jyy"], + ["ka", "kg", "ki", "kj", "kk", "kl", "km", "kn", "ko", "kr", "ks", "ku", "kv", "kw", "ky", "kaa", "kab", "kac", "kad", "kae", "kaf", "kag", "kah", "kai", "kaj", "kak", "kam", "kao", "kap", "kaq", "kar", "kav", "kaw", "kax", "kay", "kba", "kbb", "kbc", "kbd", "kbe", "kbf", "kbg", "kbh", "kbi", "kbj", "kbk", "kbl", "kbm", "kbn", "kbo", "kbp", "kbq", "kbr", "kbs", "kbt", "kbu", "kbv", "kbw", "kbx", "kby", "kbz", "kca", "kcb", "kcc", "kcd", "kce", "kcf", "kcg", "kch", "kci", "kcj", "kck", "kcl", "kcm", "kcn", "kco", "kcp", "kcq", "kcr", "kcs", "kct", "kcu", "kcv", "kcw", "kcx", "kcy", "kcz", "kda", "kdc", "kdd", "kde", "kdf", "kdg", "kdh", "kdi", "kdj", "kdk", "kdl", "kdm", "kdn", "kdo", "kdp", "kdq", "kdr", "kdt", "kdu", "kdv", "kdw", "kdx", "kdy", "kdz", "kea", "keb", "kec", "ked", "kee", "kef", "keg", "keh", "kei", "kej", "kek", "kel", "kem", "ken", "keo", "kep", "keq", "ker", "kes", "ket", "keu", "kev", "kew", "kex", "key", "kez", "kfa", "kfb", "kfc", "kfd", "kfe", "kff", "kfg", "kfh", "kfi", "kfj", "kfk", "kfl", "kfm", "kfn", "kfo", "kfp", "kfq", "kfr", "kfs", "kft", "kfu", "kfv", "kfw", "kfx", "kfy", "kfz", "kga", "kgb", "kgc", "kgd", "kge", "kgf", "kgg", "kgh", "kgi", "kgj", "kgk", "kgl", "kgm", "kgn", "kgo", "kgp", "kgq", "kgr", "kgs", "kgt", "kgu", "kgv", "kgw", "kgx", "kgy", "kha", "lyg", "khb", "khc", "khd", "khe", "khf", "khg", "khh", "khi", "khj", "khk", "khl", "khn", "kho", "khp", "khq", "khr", "khs", "kht", "khu", "khv", "khw", "khx", "khy", "khz", "kia", "kib", "kic", "kid", "kie", "kif", "kig", "kih", "kii", "kij", "kil", "kim", "kio", "kip", "kiq", "kis", "kit", "kiu", "kiv", "kiw", "kix", "kiy", "kiz", "kja", "kjb", "kjc", "kjd", "kje", "kjf", "kjg", "kjh", "kji", "kjj", "kjk", "kjl", "kjm", "kjn", "kjo", "kjp", "kjq", "kjr", "kjs", "kjt", "kju", "kjv", "kjx", "kjy", "kjz", "kka", "kkb", "kkc", "kkd", "kke", "kkf", "kkg", "kkh", "kki", "kkj", "kkk", "kkl", "kkm", "kkn", "kko", "kkp", "kkq", "kkr", "kks", "kkt", "kku", "kkv", "kkw", "kkx", "kky", "kkz", "kla", "klb", "klc", "kld", "kle", "klf", "klg", "klh", "kli", "klj", "klk", "kll", "klm", "kln", "klo", "klp", "klq", "klr", "kls", "klt", "klu", "klv", "klw", "klx", "kly", "klz", "kma", "kmb", "kmc", "kmd", "kme", "kmf", "kmg", "kmh", "kmi", "kmj", "kmk", "kml", "kmm", "kmn", "kmo", "kmp", "kmq", "kmr", "kms", "kmt", "kmu", "kmv", "kmw", "kmx", "kmy", "kmz", "kna", "knb", "knc", "knd", "kne", "knf", "kng", "kni", "knj", "knk", "knl", "knm", "knn", "kno", "knp", "knq", "knr", "kns", "knt", "knu", "knv", "knw", "knx", "kny", "knz", "koa", "koc", "kod", "koe", "kof", "kog", "koh", "koi", "koj", "kok", "kol", "koo", "kop", "koq", "kos", "kot", "kou", "kov", "kow", "kox", "koy", "koz", "kpa", "kpb", "kpc", "kpd", "kpe", "kpf", "kpg", "kph", "kpi", "kpj", "kpk", "kpl", "kpm", "kpn", "kpo", "kpp", "kpq", "kpr", "kps", "kpt", "kpu", "kpv", "kpw", "kpx", "kpy", "kpz", "kqa", "kqb", "kqc", "kqd", "kqe", "kqf", "kqg", "kqh", "kqi", "kqj", "kqk", "kql", "kqm", "kqn", "kqo", "kqp", "kqq", "kqr", "kqs", "kqt", "kqu", "kqv", "kqw", "kqx", "kqy", "kqz", "kra", "krb", "krc", "krd", "kre", "krf", "krh", "kri", "krj", "krk", "krl", "krm", "krn", "kro", "krp", "krr", "krs", "krt", "kru", "krv", "krw", "krx", "kry", "krz", "ksa", "ksb", "ksc", "ksd", "kse", "ksf", "ksg", "ksh", "ksi", "ksj", "ksk", "ksl", "ksm", "ksn", "kso", "ksp", "ksq", "ksr", "kss", "kst", "ksu", "ksv", "ksw", "ksx", "ksy", "ksz", "kta", "ktb", "ktc", "ktd", "kte", "ktf", "ktg", "kth", "kti", "ktj", "ktk", "ktl", "ktm", "ktn", "kto", "ktp", "ktq", "ktr", "kts", "ktt", "ktu", "ktv", "ktw", "ktx", "kty", "ktz", "kub", "kuc", "kud", "kue", "kuf", "kug", "kuh", "kui", "kuj", "kuk", "kul", "kum", "kun", "kuo", "kup", "kuq", "kus", "kut", "kuu", "kuv", "kuw", "kux", "kuy", "kuz", "kva", "kvb", "kvc", "kvd", "kve", "kvf", "kvg", "kvh", "kvi", "kvj", "kvk", "kvl", "kvm", "kvn", "kvo", "kvp", "kvq", "kvr", "kvs", "kvt", "kvu", "kvv", "kvw", "kvx", "kvy", "kvz", "kwa", "kwb", "kwc", "kwd", "kwe", "kwf", "kwg", "kwh", "kwi", "kwj", "kwk", "kwl", "kwm", "kwn", "kwo", "kwp", "kwq", "kwr", "kws", "kwt", "kwu", "kwv", "kww", "kwx", "kwy", "kwz", "kxa", "kxb", "kxc", "kxd", "kxe", "kxf", "kxh", "kxi", "kxj", "kxk", "kxl", "kxm", "kxn", "kxo", "kxp", "kxq", "kxr", "kxs", "kxt", "kxu", "kxv", "kxw", "kxx", "kxy", "kxz", "kya", "kyb", "kyc", "kyd", "kye", "kyf", "kyg", "kyh", "kyi", "kyj", "kyk", "kyl", "kym", "kyn", "kyo", "kyp", "kyq", "kyr", "kys", "kyt", "kyu", "kyv", "kyw", "kyx", "kyy", "kyz", "kza", "kzb", "kzc", "kzd", "kze", "kzf", "kzg", "kzh", "kzi", "kzj", "kzk", "kzl", "kzm", "kzn", "kzo", "kzp", "kzq", "kzr", "kzs", "kzt", "kzu", "kzv", "kzw", "kzx", "kzy", "kzz"], + ["la", "lb", "lg", "li", "ln", "lo", "lt", "lu", "lv", "laa", "lab", "lac", "lad", "lae", "laf", "lag", "lah", "lai", "laj", "lak", "lal", "lam", "lan", "lap", "laq", "lar", "las", "lau", "law", "lax", "lay", "laz", "lba", "lbb", "lbc", "lbe", "lbf", "lbg", "lbi", "lbj", "lbk", "lbl", "lbm", "lbn", "lbo", "lbq", "lbr", "lbs", "lbt", "lbu", "lbv", "lbw", "lbx", "lby", "lbz", "lcc", "lcd", "lce", "lcf", "lch", "lcl", "lcm", "lcp", "lcq", "lcs", "lda", "ldb", "ldd", "ldg", "ldh", "ldi", "ldj", "ldk", "ldl", "ldm", "ldn", "ldo", "ldp", "ldq", "lea", "leb", "lec", "led", "lee", "lef", "leg", "leh", "lei", "lej", "lek", "lel", "lem", "len", "leo", "lep", "leq", "ler", "les", "let", "leu", "lev", "lew", "lex", "ley", "lez", "lfa", "lfn", "lga", "lgb", "lgg", "lgh", "lgi", "lgk", "lgl", "lgm", "lgn", "lgq", "lgr", "lgt", "lgu", "lgz", "lha", "lhh", "lhi", "lhl", "lhm", "lhn", "lhp", "lhs", "lht", "lhu", "lia", "lib", "lic", "lid", "lie", "lif", "lig", "lih", "lii", "lij", "lik", "lil", "lio", "lip", "liq", "lir", "lis", "liu", "liv", "liw", "lix", "liy", "liz", "lja", "lje", "lji", "ljl", "ljp", "ljw", "ljx", "lka", "lkb", "lkc", "lkd", "lke", "lkh", "lki", "lkj", "lkl", "lkm", "lkn", "lko", "lkr", "lks", "lkt", "lku", "lky", "lla", "llb", "llc", "lld", "lle", "llf", "llg", "llh", "lli", "llj", "llk", "lll", "llm", "lln", "llo", "llp", "llq", "lls", "llu", "llx", "lma", "lmb", "lmc", "lmd", "lme", "lmf", "lmg", "lmh", "lmi", "lmj", "lmk", "lml", "lmm", "lmn", "lmo", "lmp", "lmq", "lmr", "lmu", "lmv", "lmw", "lmx", "lmy", "lmz", "lna", "lnb", "lnd", "lng", "lnh", "lni", "lnj", "lnl", "lnm", "lnn", "lno", "lns", "lnu", "lnw", "lnz", "loa", "lob", "loc", "loe", "lof", "log", "loh", "loi", "loj", "lok", "lol", "lom", "lon", "loo", "lop", "loq", "lor", "los", "lot", "lou", "lov", "low", "lox", "loy", "loz", "lpa", "lpe", "lpn", "lpo", "lpx", "lra", "lrc", "lre", "lrg", "lri", "lrk", "lrl", "lrm", "lrn", "lro", "lrr", "lrt", "lrv", "lrz", "lsa", "lsb", "lsd", "lse", "lsg", "lsh", "lsi", "lsl", "lsm", "lsn", "lso", "lsp", "lsr", "lss", "lst", "lsv", "lsy", "ltc", "ltg", "lth", "lti", "ltn", "lto", "lts", "ltu", "lua", "luc", "lud", "lue", "luf", "lui", "luj", "luk", "lul", "lum", "lun", "luo", "lup", "luq", "lur", "lus", "lut", "luu", "luv", "luw", "luy", "luz", "lva", "lvi", "lvk", "lvs", "lvu", "lwa", "lwe", "lwg", "lwh", "lwl", "lwm", "lwo", "lws", "lwt", "lwu", "lww", "lxm", "lya", "lyg", "lyn", "lzh", "lzl", "lzn", "lzz"], + ["mg", "mh", "mi", "mk", "ml", "mn", "mo", "mr", "ms", "mt", "my", "maa", "mab", "mad", "mae", "maf", "mag", "mai", "maj", "mak", "mam", "man", "map", "maq", "mas", "mat", "mau", "mav", "maw", "max", "maz", "mba", "mbb", "mbc", "mbd", "mbe", "mbf", "mbh", "mbi", "mbj", "mbk", "mbl", "mbm", "mbn", "mbo", "mbp", "mbq", "mbr", "mbs", "mbt", "mbu", "mbv", "mbw", "mbx", "mby", "mbz", "mca", "mcb", "mcc", "mcd", "mce", "mcf", "mcg", "mch", "mci", "mcj", "mck", "mcl", "mcm", "mcn", "mco", "mcp", "mcq", "mcr", "mcs", "mct", "mcu", "mcv", "mcw", "mcx", "mcy", "mcz", "mda", "mdb", "mdc", "mdd", "mde", "mdf", "mdg", "mdh", "mdi", "mdj", "mdk", "mdl", "mdm", "mdn", "mdp", "mdq", "mdr", "mds", "mdt", "mdu", "mdv", "mdw", "mdx", "mdy", "mdz", "mea", "meb", "mec", "med", "mee", "mef", "meg", "meh", "mei", "mej", "mek", "mel", "mem", "men", "meo", "mep", "meq", "mer", "mes", "met", "meu", "mev", "mew", "mey", "mez", "mfa", "mfb", "mfc", "mfd", "mfe", "mff", "mfg", "mfh", "mfi", "mfj", "mfk", "mfl", "mfm", "mfn", "mfo", "mfp", "mfq", "mfr", "mfs", "mft", "mfu", "mfv", "mfw", "mfx", "mfy", "mfz", "mga", "mgb", "mgc", "mgd", "mge", "mgf", "mgg", "mgh", "mgi", "mgj", "mgk", "mgl", "mgm", "mgn", "mgo", "mgp", "mgq", "mgr", "mgs", "mgt", "mgu", "mgv", "mgw", "mgx", "mgy", "mgz", "mha", "mhb", "mhc", "mhd", "mhe", "mhf", "mhg", "mhh", "mhi", "mhj", "mhk", "mhl", "mhm", "mhn", "mho", "mhp", "mhq", "mhr", "mhs", "mht", "mhu", "mhw", "mhx", "mhy", "mhz", "mia", "mib", "mic", "mid", "mie", "mif", "mig", "mih", "mii", "mij", "mik", "mil", "mim", "min", "mio", "mip", "miq", "mir", "mis", "mit", "miu", "miw", "mix", "miy", "miz", "mja", "mjb", "mjc", "mjd", "mje", "mjg", "mjh", "mji", "mjj", "mjk", "mjl", "mjm", "mjn", "mjo", "mjp", "mjq", "mjr", "mjs", "mjt", "mju", "mjv", "mjw", "mjx", "mjy", "mjz", "mka", "mkb", "mkc", "mke", "mkf", "mkg", "mkh", "mki", "mkj", "mkk", "mkl", "mkm", "mkn", "mko", "mkp", "mkq", "mkr", "mks", "mkt", "mku", "mkv", "mkw", "mkx", "mky", "mkz", "mla", "mlb", "mlc", "mld", "mle", "mlf", "mlh", "mli", "mlj", "mlk", "mll", "mlm", "mln", "mlo", "mlp", "mlq", "mlr", "mls", "mlu", "mlv", "mlw", "mlx", "mlz", "mma", "mmb", "mmc", "mmd", "mme", "mmf", "mmg", "mmh", "mmi", "mmj", "mmk", "mml", "mmm", "mmn", "mmo", "mmp", "mmq", "mmr", "mmt", "mmu", "mmv", "mmw", "mmx", "mmy", "mmz", "mna", "mnb", "mnc", "mnd", "mne", "mnf", "mng", "mnh", "mni", "mnj", "mnk", "mnl", "mnm", "mnn", "mno", "mnp", "mnq", "mnr", "mns", "mnt", "mnu", "mnv", "mnw", "mnx", "mny", "mnz", "moa", "moc", "mod", "moe", "mof", "mog", "moh", "moi", "moj", "mok", "mom", "moo", "mop", "moq", "mor", "mos", "mot", "mou", "mov", "mow", "mox", "moy", "moz", "mpa", "mpb", "mpc", "mpd", "mpe", "mpg", "mph", "mpi", "mpj", "mpk", "mpl", "mpm", "mpn", "mpo", "mpp", "mpq", "mpr", "mps", "mpt", "mpu", "mpv", "mpw", "mpx", "mpy", "mpz", "mqa", "mqb", "mqc", "mqe", "mqf", "mqg", "mqh", "mqi", "mqj", "mqk", "mql", "mqm", "mqn", "mqo", "mqp", "mqq", "mqr", "mqs", "mqt", "mqu", "mqv", "mqw", "mqx", "mqy", "mqz", "mra", "mrb", "mrc", "mrd", "mre", "mrf", "mrg", "mrh", "mrj", "mrk", "mrl", "mrm", "mrn", "mro", "mrp", "mrq", "mrr", "mrs", "mrt", "mru", "mrv", "mrw", "mrx", "mry", "mrz", "msb", "msc", "msd", "mse", "msf", "msg", "msh", "msi", "msj", "msk", "msl", "msm", "msn", "mso", "msp", "msq", "msr", "mss", "mst", "msu", "msv", "msw", "msx", "msy", "msz", "mta", "mtb", "mtc", "mtd", "mte", "mtf", "mtg", "mth", "mti", "mtj", "mtk", "mtl", "mtm", "mtn", "mto", "mtp", "mtq", "mtr", "mts", "mtt", "mtu", "mtv", "mtw", "mtx", "mty", "mua", "mub", "muc", "mud", "mue", "mug", "muh", "mui", "muj", "muk", "mul", "mum", "mun", "muo", "mup", "muq", "mur", "mus", "mut", "muu", "muv", "mux", "muy", "muz", "mva", "mvb", "mvd", "mve", "mvf", "mvg", "mvh", "mvi", "mvk", "mvl", "mvm", "mvn", "mvo", "mvp", "mvq", "mvr", "mvs", "mvt", "mvu", "mvv", "mvw", "mvx", "mvy", "mvz", "mwa", "mwb", "mwc", "mwd", "mwe", "mwf", "mwg", "mwh", "mwi", "mwj", "mwk", "mwl", "mwm", "mwn", "mwo", "mwp", "mwq", "mwr", "mws", "mwt", "mwu", "mwv", "mww", "mwx", "mwy", "mwz", "mxa", "mxb", "mxc", "mxd", "mxe", "mxf", "mxg", "mxh", "mxi", "mxj", "mxk", "mxl", "mxm", "mxn", "mxo", "mxp", "mxq", "mxr", "mxs", "mxt", "mxu", "mxv", "mxw", "mxx", "mxy", "mxz", "myb", "myc", "myd", "mye", "myf", "myg", "myh", "myi", "myj", "myk", "myl", "mym", "myn", "myo", "myp", "myq", "myr", "mys", "myt", "myu", "myv", "myw", "myx", "myy", "myz", "mza", "mzb", "mzc", "mzd", "mze", "mzg", "mzh", "mzi", "mzj", "mzk", "mzl", "mzm", "mzn", "mzo", "mzp", "mzq", "mzr", "mzs", "mzt", "mzu", "mzv", "mzw", "mzx", "mzy", "mzz"], + ["na", "nb", "nd", "ne", "ng", "nl", "nn", "no", "nr", "nv", "ny", "naa", "nab", "nac", "nad", "nae", "naf", "nag", "nah", "nai", "naj", "nak", "nal", "nam", "nan", "nao", "nap", "naq", "nar", "nas", "nat", "naw", "nax", "nay", "naz", "nba", "nbb", "nbc", "nbd", "nbe", "nbf", "nbg", "nbh", "nbi", "nbj", "nbk", "nbm", "nbn", "nbo", "nbp", "nbq", "nbr", "nbs", "nbt", "nbu", "nbv", "nbw", "nbx", "nby", "nca", "ncb", "ncc", "ncd", "nce", "ncf", "ncg", "nch", "nci", "ncj", "nck", "ncl", "ncm", "ncn", "nco", "ncp", "ncq", "ncr", "ncs", "nct", "ncu", "ncx", "ncz", "nda", "ndb", "ndc", "ndd", "ndf", "ndg", "ndh", "ndi", "ndj", "ndk", "ndl", "ndm", "ndn", "ndp", "ndq", "ndr", "nds", "ndt", "ndu", "ndv", "ndw", "ndx", "ndy", "ndz", "nea", "neb", "nec", "ned", "nee", "nef", "neg", "neh", "nei", "nej", "nek", "nem", "nen", "neo", "neq", "ner", "nes", "net", "neu", "nev", "new", "nex", "ney", "nez", "nfa", "nfd", "nfl", "nfr", "nfu", "nga", "ngb", "ngc", "ngd", "nge", "ngf", "ngg", "ngh", "ngi", "ngj", "ngk", "ngl", "ngm", "ngn", "ngo", "ngp", "ngq", "ngr", "ngs", "ngt", "ngu", "ngv", "ngw", "ngx", "ngy", "ngz", "nha", "nhb", "nhc", "nhd", "nhe", "nhf", "nhg", "nhh", "nhi", "nhk", "nhm", "nhn", "nho", "nhp", "nhq", "nhr", "nht", "nhu", "nhv", "nhw", "nhx", "nhy", "nhz", "nia", "nib", "nic", "nid", "nie", "nif", "nig", "nih", "nii", "nij", "nik", "nil", "nim", "nin", "nio", "niq", "nir", "nis", "nit", "niu", "niv", "niw", "nix", "niy", "niz", "nja", "njb", "njd", "njh", "nji", "njj", "njl", "njm", "njn", "njo", "njr", "njs", "njt", "nju", "njx", "njy", "njz", "nka", "nkb", "nkc", "nkd", "nke", "nkf", "nkg", "nkh", "nki", "nkj", "nkk", "nkm", "nkn", "nko", "nkp", "nkq", "nkr", "nks", "nkt", "nku", "nkv", "nkw", "nkx", "nkz", "nla", "nlc", "nle", "nlg", "nli", "nlj", "nlk", "nll", "nlm", "nln", "nlo", "nlq", "nlr", "nlu", "nlv", "nlw", "nlx", "nly", "nlz", "nma", "nmb", "nmc", "nmd", "nme", "nmf", "nmg", "nmh", "nmi", "nmj", "nmk", "nml", "nmm", "nmn", "nmo", "nmp", "nmq", "nmr", "nms", "nmt", "nmu", "nmv", "nmw", "nmx", "nmy", "nmz", "nna", "nnb", "nnc", "nnd", "nne", "nnf", "nng", "nnh", "nni", "nnj", "nnk", "nnl", "nnm", "nnn", "nnp", "nnq", "nnr", "nns", "nnt", "nnu", "nnv", "nnw", "nnx", "nny", "nnz", "noa", "noc", "nod", "noe", "nof", "nog", "noh", "noi", "noj", "nok", "nol", "nom", "non", "noo", "nop", "noq", "nos", "not", "nou", "nov", "now", "noy", "noz", "npa", "npb", "npg", "nph", "npi", "npl", "npn", "npo", "nps", "npu", "npx", "npy", "nqg", "nqk", "nql", "nqm", "nqn", "nqo", "nqq", "nqt", "nqy", "nra", "nrb", "nrc", "nre", "nrf", "nrg", "nri", "nrk", "nrl", "nrm", "nrn", "nrp", "nrr", "nrt", "nru", "nrx", "nrz", "nsa", "nsb", "nsc", "nsd", "nse", "nsf", "nsg", "nsh", "nsi", "nsk", "nsl", "nsm", "nsn", "nso", "nsp", "nsq", "nsr", "nss", "nst", "nsu", "nsv", "nsw", "nsx", "nsy", "nsz", "ntd", "nte", "ntg", "nti", "ntj", "ntk", "ntm", "nto", "ntp", "ntr", "nts", "ntu", "ntw", "ntx", "nty", "ntz", "nua", "nub", "nuc", "nud", "nue", "nuf", "nug", "nuh", "nui", "nuj", "nuk", "nul", "num", "nun", "nuo", "nup", "nuq", "nur", "nus", "nut", "nuu", "nuv", "nuw", "nux", "nuy", "nuz", "nvh", "nvm", "nvo", "nwa", "nwb", "nwc", "nwe", "nwg", "nwi", "nwm", "nwo", "nwr", "nwx", "nwy", "nxa", "nxd", "nxe", "nxg", "nxi", "nxk", "nxl", "nxm", "nxn", "nxo", "nxq", "nxr", "nxu", "nxx", "nyb", "nyc", "nyd", "nye", "nyf", "nyg", "nyh", "nyi", "nyj", "nyk", "nyl", "nym", "nyn", "nyo", "nyp", "nyq", "nyr", "nys", "nyt", "nyu", "nyv", "nyw", "nyx", "nyy", "nza", "nzb", "nzd", "nzi", "nzk", "nzm", "nzs", "nzu", "nzy", "nzz"], + ["oc", "oj", "om", "or", "os", "oaa", "oac", "oar", "oav", "obi", "obk", "obl", "obm", "obo", "obr", "obt", "obu", "oca", "och", "ocm", "oco", "ocu", "oda", "odk", "odt", "odu", "ofo", "ofs", "ofu", "ogb", "ogc", "oge", "ogg", "ogo", "ogu", "oht", "ohu", "oia", "oin", "ojb", "ojc", "ojg", "ojp", "ojs", "ojv", "ojw", "oka", "okb", "okc", "okd", "oke", "okg", "okh", "oki", "okj", "okk", "okl", "okm", "okn", "oko", "okr", "oks", "oku", "okv", "okx", "okz", "ola", "old", "ole", "olk", "olm", "olo", "olr", "olt", "olu", "oma", "omb", "omc", "ome", "omg", "omi", "omk", "oml", "omn", "omo", "omp", "omq", "omr", "omt", "omu", "omv", "omw", "omx", "omy", "ona", "onb", "one", "ong", "oni", "onj", "onk", "onn", "ono", "onp", "onr", "ons", "ont", "onu", "onw", "onx", "ood", "oog", "oon", "oor", "oos", "opa", "opk", "opm", "opo", "opt", "opy", "ora", "orc", "ore", "org", "orh", "orn", "oro", "orr", "ors", "ort", "oru", "orv", "orw", "orx", "ory", "orz", "osa", "osc", "osi", "osn", "oso", "osp", "ost", "osu", "osx", "ota", "otb", "otd", "ote", "oti", "otk", "otl", "otm", "otn", "oto", "otq", "otr", "ots", "ott", "otu", "otw", "otx", "oty", "otz", "oua", "oub", "oue", "oui", "oum", "oun", "ovd", "owi", "owl", "oyb", "oyd", "oym", "oyy", "ozm"], + ["pa", "pi", "pl", "ps", "pt", "paa", "pab", "pac", "pad", "pae", "paf", "pag", "pah", "pai", "pak", "pal", "pam", "pao", "pap", "paq", "par", "pas", "pat", "pau", "pav", "paw", "pax", "pay", "paz", "pbb", "pbc", "pbe", "pbf", "pbg", "pbh", "pbi", "pbl", "pbm", "pbn", "pbo", "pbp", "pbr", "pbs", "pbt", "pbu", "pbv", "pby", "pbz", "pca", "pcb", "pcc", "pcd", "pce", "pcf", "pcg", "pch", "pci", "pcj", "pck", "pcl", "pcm", "pcn", "pcp", "pcr", "pcw", "pda", "pdc", "pdi", "pdn", "pdo", "pdt", "pdu", "pea", "peb", "ped", "pee", "pef", "peg", "peh", "pei", "pej", "pek", "pel", "pem", "peo", "pep", "peq", "pes", "pev", "pex", "pey", "pez", "pfa", "pfe", "pfl", "pga", "pgd", "pgg", "pgi", "pgk", "pgl", "pgn", "pgs", "pgu", "pgy", "pgz", "pha", "phd", "phg", "phh", "phi", "phk", "phl", "phm", "phn", "pho", "phq", "phr", "pht", "phu", "phv", "phw", "pia", "pib", "pic", "pid", "pie", "pif", "pig", "pih", "pii", "pij", "pil", "pim", "pin", "pio", "pip", "pir", "pis", "pit", "piu", "piv", "piw", "pix", "piy", "piz", "pjt", "pka", "pkb", "pkc", "pkg", "pkh", "pkn", "pko", "pkp", "pkr", "pks", "pkt", "pku", "pla", "plb", "plc", "pld", "ple", "plf", "plg", "plh", "plj", "plk", "pll", "pln", "plo", "plp", "plq", "plr", "pls", "plt", "plu", "plv", "plw", "ply", "plz", "pma", "pmb", "pmc", "pmd", "pme", "pmf", "pmh", "pmi", "pmj", "pmk", "pml", "pmm", "pmn", "pmo", "pmq", "pmr", "pms", "pmt", "pmu", "pmw", "pmx", "pmy", "pmz", "pna", "pnb", "pnc", "pnd", "pne", "png", "pnh", "pni", "pnj", "pnk", "pnl", "pnm", "pnn", "pno", "pnp", "pnq", "pnr", "pns", "pnt", "pnu", "pnv", "pnw", "pnx", "pny", "pnz", "poc", "pod", "poe", "pof", "pog", "poh", "poi", "pok", "pom", "pon", "poo", "pop", "poq", "pos", "pot", "pov", "pow", "pox", "poy", "poz", "ppa", "ppe", "ppi", "ppk", "ppl", "ppm", "ppn", "ppo", "ppp", "ppq", "ppr", "pps", "ppt", "ppu", "pqa", "pqe", "pqm", "pqw", "pra", "prb", "prc", "prd", "pre", "prf", "prg", "prh", "pri", "prk", "prl", "prm", "prn", "pro", "prp", "prq", "prr", "prs", "prt", "pru", "prw", "prx", "pry", "prz", "psa", "psc", "psd", "pse", "psg", "psh", "psi", "psl", "psm", "psn", "pso", "psp", "psq", "psr", "pss", "pst", "psu", "psw", "psy", "pta", "pth", "pti", "ptn", "pto", "ptp", "ptq", "ptr", "ptt", "ptu", "ptv", "ptw", "pty", "pua", "pub", "puc", "pud", "pue", "puf", "pug", "pui", "puj", "puk", "pum", "puo", "pup", "puq", "pur", "put", "puu", "puw", "pux", "puy", "puz", "pwa", "pwb", "pwg", "pwi", "pwm", "pwn", "pwo", "pwr", "pww", "pxm", "pye", "pym", "pyn", "pys", "pyu", "pyx", "pyy", "pzn"], + ["qu", "qua", "qub", "quc", "qud", "quf", "qug", "quh", "qui", "quk", "qul", "qum", "qun", "qup", "quq", "qur", "qus", "quv", "quw", "qux", "quy", "quz", "qva", "qvc", "qve", "qvh", "qvi", "qvj", "qvl", "qvm", "qvn", "qvo", "qvp", "qvs", "qvw", "qvy", "qvz", "qwa", "qwc", "qwe", "qwh", "qwm", "qws", "qwt", "qxa", "qxc", "qxh", "qxl", "qxn", "qxo", "qxp", "qxq", "qxr", "qxs", "qxt", "qxu", "qxw", "qya", "qyp"], + ["rm", "rn", "ro", "ru", "rw", "raa", "rab", "rac", "rad", "raf", "rag", "rah", "rai", "raj", "rak", "ral", "ram", "ran", "rao", "rap", "raq", "rar", "ras", "rat", "rau", "rav", "raw", "rax", "ray", "raz", "rbb", "rbk", "rbl", "rbp", "rcf", "rdb", "rea", "reb", "ree", "reg", "rei", "rej", "rel", "rem", "ren", "rer", "res", "ret", "rey", "rga", "rge", "rgk", "rgn", "rgr", "rgs", "rgu", "rhg", "rhp", "ria", "rie", "rif", "ril", "rim", "rin", "rir", "rit", "riu", "rjg", "rji", "rjs", "rka", "rkb", "rkh", "rki", "rkm", "rkt", "rkw", "rma", "rmb", "rmc", "rmd", "rme", "rmf", "rmg", "rmh", "rmi", "rmk", "rml", "rmm", "rmn", "rmo", "rmp", "rmq", "rmr", "rms", "rmt", "rmu", "rmv", "rmw", "rmx", "rmy", "rmz", "rna", "rnd", "rng", "rnl", "rnn", "rnp", "rnr", "rnw", "roa", "rob", "roc", "rod", "roe", "rof", "rog", "rol", "rom", "roo", "rop", "ror", "rou", "row", "rpn", "rpt", "rri", "rro", "rrt", "rsb", "rsi", "rsl", "rsm", "rtc", "rth", "rtm", "rts", "rtw", "rub", "ruc", "rue", "ruf", "rug", "ruh", "rui", "ruk", "ruo", "rup", "ruq", "rut", "ruu", "ruy", "ruz", "rwa", "rwk", "rwl", "rwm", "rwo", "rwr", "rxd", "rxw", "ryn", "rys", "ryu", "rzh"], + ["sa", "sc", "sd", "se", "sg", "sh", "si", "sk", "sl", "sm", "sn", "so", "sq", "sr", "ss", "st", "su", "sv", "sw", "saa", "sab", "sac", "sad", "sae", "saf", "sah", "sai", "saj", "sak", "sal", "sam", "sao", "sap", "saq", "sar", "sas", "sat", "sau", "sav", "saw", "sax", "say", "saz", "sba", "sbb", "sbc", "sbd", "sbe", "sbf", "sbg", "sbh", "sbi", "sbj", "sbk", "sbl", "sbm", "sbn", "sbo", "sbp", "sbq", "sbr", "sbs", "sbt", "sbu", "sbv", "sbw", "sbx", "sby", "sbz", "sca", "scb", "sce", "scf", "scg", "sch", "sci", "sck", "scl", "scn", "sco", "scp", "scq", "scs", "sct", "scu", "scv", "scw", "scx", "sda", "sdb", "sdc", "sde", "sdf", "sdg", "sdh", "sdj", "sdk", "sdl", "sdm", "sdn", "sdo", "sdp", "sdq", "sdr", "sds", "sdt", "sdu", "sdv", "sdx", "sdz", "sea", "seb", "sec", "sed", "see", "sef", "seg", "seh", "sei", "sej", "sek", "sel", "sem", "sen", "seo", "sep", "seq", "ser", "ses", "set", "seu", "sev", "sew", "sey", "sez", "sfb", "sfe", "sfm", "sfs", "sfw", "sga", "sgb", "sgc", "sgd", "sge", "sgg", "sgh", "sgi", "sgj", "sgk", "sgl", "sgm", "sgn", "sgo", "sgp", "sgr", "sgs", "sgt", "sgu", "sgw", "sgx", "sgy", "sgz", "sha", "shb", "shc", "shd", "she", "shg", "shh", "shi", "shj", "shk", "shl", "shm", "shn", "sho", "shp", "shq", "shr", "shs", "sht", "shu", "shv", "shw", "shx", "shy", "shz", "sia", "sib", "sid", "sie", "sif", "sig", "sih", "sii", "sij", "sik", "sil", "sim", "sio", "sip", "siq", "sir", "sis", "sit", "siu", "siv", "siw", "six", "siy", "siz", "sja", "sjb", "sjd", "sje", "sjg", "sjk", "sjl", "sjm", "sjn", "sjo", "sjp", "sjr", "sjs", "sjt", "sju", "sjw", "ska", "skb", "skc", "skd", "ske", "skf", "skg", "skh", "ski", "skj", "skk", "skm", "skn", "sko", "skp", "skq", "skr", "sks", "skt", "sku", "skv", "skw", "skx", "sky", "skz", "sla", "slc", "sld", "sle", "slf", "slg", "slh", "sli", "slj", "sll", "slm", "sln", "slp", "slq", "slr", "sls", "slt", "slu", "slw", "slx", "sly", "slz", "sma", "smb", "smc", "smd", "smf", "smg", "smh", "smi", "smj", "smk", "sml", "smm", "smn", "smp", "smq", "smr", "sms", "smt", "smu", "smv", "smw", "smx", "smy", "smz", "snb", "snc", "sne", "snf", "sng", "snh", "sni", "snj", "snk", "snl", "snm", "snn", "sno", "snp", "snq", "snr", "sns", "snu", "snv", "snw", "snx", "sny", "snz", "soa", "sob", "soc", "sod", "soe", "sog", "soh", "soi", "soj", "sok", "sol", "son", "soo", "sop", "soq", "sor", "sos", "sou", "sov", "sow", "sox", "soy", "soz", "spb", "spc", "spd", "spe", "spg", "spi", "spk", "spl", "spm", "spn", "spo", "spp", "spq", "spr", "sps", "spt", "spu", "spv", "spx", "spy", "sqa", "sqh", "sqj", "sqk", "sqm", "sqn", "sqo", "sqq", "sqr", "sqs", "sqt", "squ", "sqx", "sra", "srb", "src", "sre", "srf", "srg", "srh", "sri", "srk", "srl", "srm", "srn", "sro", "srq", "srr", "srs", "srt", "sru", "srv", "srw", "srx", "sry", "srz", "ssa", "ssb", "ssc", "ssd", "sse", "ssf", "ssg", "ssh", "ssi", "ssj", "ssk", "ssl", "ssm", "ssn", "sso", "ssp", "ssq", "ssr", "sss", "sst", "ssu", "ssv", "ssx", "ssy", "ssz", "sta", "stb", "std", "ste", "stf", "stg", "sth", "sti", "stj", "stk", "stl", "stm", "stn", "sto", "stp", "stq", "str", "sts", "stt", "stu", "stv", "stw", "sty", "sua", "sub", "suc", "sue", "sug", "sui", "suj", "suk", "sul", "sum", "suo", "suq", "sur", "sus", "sut", "suv", "suw", "sux", "suy", "suz", "sva", "svb", "svc", "sve", "svk", "svm", "svr", "svs", "svx", "swb", "swc", "swf", "swg", "swh", "swi", "swj", "swk", "swl", "swm", "swn", "swo", "swp", "swq", "swr", "sws", "swt", "swu", "swv", "sww", "swx", "swy", "sxb", "sxc", "sxe", "sxg", "sxk", "sxl", "sxm", "sxn", "sxo", "sxr", "sxs", "sxu", "sxw", "sya", "syb", "syc", "syd", "syi", "syk", "syl", "sym", "syn", "syo", "syr", "sys", "syw", "syx", "syy", "sza", "szb", "szc", "szd", "sze", "szg", "szl", "szn", "szp", "szs", "szv", "szw", "szy"], + ["ta", "te", "tg", "th", "ti", "tk", "tl", "tn", "to", "tr", "ts", "tt", "tw", "ty", "taa", "tab", "tac", "tad", "tae", "taf", "tag", "tai", "taj", "tak", "tal", "tan", "tao", "tap", "taq", "tar", "tas", "tau", "tav", "taw", "tax", "tay", "taz", "tba", "tbb", "tbc", "tbd", "tbe", "tbf", "tbg", "tbh", "tbi", "tbj", "tbk", "tbl", "tbm", "tbn", "tbo", "tbp", "tbq", "tbr", "tbs", "tbt", "tbu", "tbv", "tbw", "tbx", "tby", "tbz", "tca", "tcb", "tcc", "tcd", "tce", "tcf", "tcg", "tch", "tci", "tck", "tcl", "tcm", "tcn", "tco", "tcp", "tcq", "tcs", "tct", "tcu", "tcw", "tcx", "tcy", "tcz", "tda", "tdb", "tdc", "tdd", "tde", "tdf", "tdg", "tdh", "tdi", "tdj", "tdk", "tdl", "tdm", "tdn", "tdo", "tdq", "tdr", "tds", "tdt", "tdu", "tdv", "tdx", "tdy", "tea", "teb", "tec", "ted", "tee", "tef", "teg", "teh", "tei", "tek", "tem", "ten", "teo", "tep", "teq", "ter", "tes", "tet", "teu", "tev", "tew", "tex", "tey", "tez", "tfi", "tfn", "tfo", "tfr", "tft", "tga", "tgb", "tgc", "tgd", "tge", "tgf", "tgg", "tgh", "tgi", "tgj", "tgn", "tgo", "tgp", "tgq", "tgr", "tgs", "tgt", "tgu", "tgv", "tgw", "tgx", "tgy", "tgz", "thc", "thd", "the", "thf", "thh", "thi", "thk", "thl", "thm", "thn", "thp", "thq", "thr", "ths", "tht", "thu", "thv", "thw", "thx", "thy", "thz", "tia", "tic", "tid", "tie", "tif", "tig", "tih", "tii", "tij", "tik", "til", "tim", "tin", "tio", "tip", "tiq", "tis", "tit", "tiu", "tiv", "tiw", "tix", "tiy", "tiz", "tja", "tjg", "tji", "tjj", "tjl", "tjm", "tjn", "tjo", "tjp", "tjs", "tju", "tjw", "tka", "tkb", "tkd", "tke", "tkf", "tkg", "tkk", "tkl", "tkm", "tkn", "tkp", "tkq", "tkr", "tks", "tkt", "tku", "tkv", "tkw", "tkx", "tkz", "tla", "tlb", "tlc", "tld", "tlf", "tlg", "tlh", "tli", "tlj", "tlk", "tll", "tlm", "tln", "tlo", "tlp", "tlq", "tlr", "tls", "tlt", "tlu", "tlv", "tlw", "tlx", "tly", "tma", "tmb", "tmc", "tmd", "tme", "tmf", "tmg", "tmh", "tmi", "tmj", "tmk", "tml", "tmm", "tmn", "tmo", "tmp", "tmq", "tmr", "tms", "tmt", "tmu", "tmv", "tmw", "tmy", "tmz", "tna", "tnb", "tnc", "tnd", "tne", "tnf", "tng", "tnh", "tni", "tnk", "tnl", "tnm", "tnn", "tno", "tnp", "tnq", "tnr", "tns", "tnt", "tnu", "tnv", "tnw", "tnx", "tny", "tnz", "tob", "toc", "tod", "toe", "tof", "tog", "toh", "toi", "toj", "tol", "tom", "too", "top", "toq", "tor", "tos", "tou", "tov", "tow", "tox", "toy", "toz", "tpa", "tpc", "tpe", "tpf", "tpg", "tpi", "tpj", "tpk", "tpl", "tpm", "tpn", "tpo", "tpp", "tpq", "tpr", "tpt", "tpu", "tpv", "tpw", "tpx", "tpy", "tpz", "tqb", "tql", "tqm", "tqn", "tqo", "tqp", "tqq", "tqr", "tqt", "tqu", "tqw", "tra", "trb", "trc", "trd", "tre", "trf", "trg", "trh", "tri", "trj", "trk", "trl", "trm", "trn", "tro", "trp", "trq", "trr", "trs", "trt", "tru", "trv", "trw", "trx", "try", "trz", "tsa", "tsb", "tsc", "tsd", "tse", "tsf", "tsg", "tsh", "tsi", "tsj", "tsk", "tsl", "tsm", "tsp", "tsq", "tsr", "tss", "tst", "tsu", "tsv", "tsw", "tsx", "tsy", "tsz", "tta", "ttb", "ttc", "ttd", "tte", "ttf", "ttg", "tth", "tti", "ttj", "ttk", "ttl", "ttm", "ttn", "tto", "ttp", "ttq", "ttr", "tts", "ttt", "ttu", "ttv", "ttw", "tty", "ttz", "tua", "tub", "tuc", "tud", "tue", "tuf", "tug", "tuh", "tui", "tuj", "tul", "tum", "tun", "tuo", "tup", "tuq", "tus", "tut", "tuu", "tuv", "tuw", "tux", "tuy", "tuz", "tva", "tvd", "tve", "tvk", "tvl", "tvm", "tvn", "tvo", "tvs", "tvt", "tvu", "tvw", "tvx", "tvy", "twa", "twb", "twc", "twd", "twe", "twf", "twg", "twh", "twl", "twm", "twn", "two", "twp", "twq", "twr", "twt", "twu", "tww", "twx", "twy", "txa", "txb", "txc", "txe", "txg", "txh", "txi", "txj", "txm", "txn", "txo", "txq", "txr", "txs", "txt", "txu", "txx", "txy", "tya", "tye", "tyh", "tyi", "tyj", "tyl", "tyn", "typ", "tyr", "tys", "tyt", "tyu", "tyv", "tyx", "tyy", "tyz", "tza", "tzh", "tzj", "tzl", "tzm", "tzn", "tzo", "tzx"], + ["ug", "uk", "ur", "uz", "uam", "uan", "uar", "uba", "ubi", "ubl", "ubr", "ubu", "uby", "uda", "ude", "udg", "udi", "udj", "udl", "udm", "udu", "ues", "ufi", "uga", "ugb", "uge", "ugn", "ugo", "ugy", "uha", "uhn", "uis", "uiv", "uji", "uka", "ukg", "ukh", "uki", "ukk", "ukl", "ukp", "ukq", "uks", "uku", "ukv", "ukw", "uky", "ula", "ulb", "ulc", "ule", "ulf", "uli", "ulk", "ull", "ulm", "uln", "ulu", "ulw", "uma", "umb", "umc", "umd", "umg", "umi", "umm", "umn", "umo", "ump", "umr", "ums", "umu", "una", "und", "une", "ung", "uni", "unk", "unm", "unn", "unp", "unr", "unu", "unx", "unz", "uok", "upi", "upv", "ura", "urb", "urc", "ure", "urf", "urg", "urh", "uri", "urj", "urk", "url", "urm", "urn", "uro", "urp", "urr", "urt", "uru", "urv", "urw", "urx", "ury", "urz", "usa", "ush", "usi", "usk", "usp", "uss", "usu", "uta", "ute", "uth", "utp", "utr", "utu", "uum", "uun", "uur", "uuu", "uve", "uvh", "uvl", "uwa", "uya", "uzn", "uzs"], + ["ve", "vi", "vo", "vaa", "vae", "vaf", "vag", "vah", "vai", "vaj", "val", "vam", "van", "vao", "vap", "var", "vas", "vau", "vav", "vay", "vbb", "vbk", "vec", "ved", "vel", "vem", "veo", "vep", "ver", "vgr", "vgt", "vic", "vid", "vif", "vig", "vil", "vin", "vis", "vit", "viv", "vka", "vki", "vkj", "vkk", "vkl", "vkm", "vkn", "vko", "vkp", "vkt", "vku", "vkz", "vlp", "vls", "vma", "vmb", "vmc", "vmd", "vme", "vmf", "vmg", "vmh", "vmi", "vmj", "vmk", "vml", "vmm", "vmp", "vmq", "vmr", "vms", "vmu", "vmv", "vmw", "vmx", "vmy", "vmz", "vnk", "vnm", "vnp", "vor", "vot", "vra", "vro", "vrs", "vrt", "vsi", "vsl", "vsv", "vto", "vum", "vun", "vut", "vwa"], + ["wa", "wo", "waa", "wab", "wac", "wad", "wae", "waf", "wag", "wah", "wai", "waj", "wak", "wal", "wam", "wan", "wao", "wap", "waq", "war", "was", "wat", "wau", "wav", "waw", "wax", "way", "waz", "wba", "wbb", "wbe", "wbf", "wbh", "wbi", "wbj", "wbk", "wbl", "wbm", "wbp", "wbq", "wbr", "wbs", "wbt", "wbv", "wbw", "wca", "wci", "wdd", "wdg", "wdj", "wdk", "wdu", "wdy", "wea", "wec", "wed", "weg", "weh", "wei", "wem", "wen", "weo", "wep", "wer", "wes", "wet", "weu", "wew", "wfg", "wga", "wgb", "wgg", "wgi", "wgo", "wgu", "wgw", "wgy", "wha", "whg", "whk", "whu", "wib", "wic", "wie", "wif", "wig", "wih", "wii", "wij", "wik", "wil", "wim", "win", "wir", "wit", "wiu", "wiv", "wiw", "wiy", "wja", "wji", "wka", "wkb", "wkd", "wkl", "wkr", "wku", "wkw", "wky", "wla", "wlc", "wle", "wlg", "wlh", "wli", "wlk", "wll", "wlm", "wlo", "wlr", "wls", "wlu", "wlv", "wlw", "wlx", "wly", "wma", "wmb", "wmc", "wmd", "wme", "wmg", "wmh", "wmi", "wmm", "wmn", "wmo", "wms", "wmt", "wmw", "wmx", "wnb", "wnc", "wnd", "wne", "wng", "wni", "wnk", "wnm", "wnn", "wno", "wnp", "wnu", "wnw", "wny", "woa", "wob", "woc", "wod", "woe", "wof", "wog", "woi", "wok", "wom", "won", "woo", "wor", "wos", "wow", "woy", "wpc", "wra", "wrb", "wrd", "wrg", "wrh", "wri", "wrk", "wrl", "wrm", "wrn", "wro", "wrp", "wrr", "wrs", "wru", "wrv", "wrw", "wrx", "wry", "wrz", "wsa", "wsg", "wsi", "wsk", "wsr", "wss", "wsu", "wsv", "wtf", "wth", "wti", "wtk", "wtm", "wtw", "wua", "wub", "wud", "wuh", "wul", "wum", "wun", "wur", "wut", "wuu", "wuv", "wux", "wuy", "wwa", "wwb", "wwo", "wwr", "www", "wxa", "wxw", "wya", "wyb", "wyi", "wym", "wyr", "wyy"], + ["xh", "xaa", "xab", "xac", "xad", "xae", "xag", "xai", "xaj", "xak", "xal", "xam", "xan", "xao", "xap", "xaq", "xar", "xas", "xat", "xau", "xav", "xaw", "xay", "xba", "xbb", "xbc", "xbd", "xbe", "xbg", "xbi", "xbj", "xbm", "xbn", "xbo", "xbp", "xbr", "xbw", "xbx", "xby", "xcb", "xcc", "xce", "xcg", "xch", "xcl", "xcm", "xcn", "xco", "xcr", "xct", "xcu", "xcv", "xcw", "xcy", "xda", "xdc", "xdk", "xdm", "xdo", "xdy", "xeb", "xed", "xeg", "xel", "xem", "xep", "xer", "xes", "xet", "xeu", "xfa", "xga", "xgb", "xgd", "xgf", "xgg", "xgi", "xgl", "xgm", "xgn", "xgr", "xgu", "xgw", "xha", "xhc", "xhd", "xhe", "xhr", "xht", "xhu", "xhv", "xia", "xib", "xii", "xil", "xin", "xip", "xir", "xis", "xiv", "xiy", "xjb", "xjt", "xka", "xkb", "xkc", "xkd", "xke", "xkf", "xkg", "xkh", "xki", "xkj", "xkk", "xkl", "xkn", "xko", "xkp", "xkq", "xkr", "xks", "xkt", "xku", "xkv", "xkw", "xkx", "xky", "xkz", "xla", "xlb", "xlc", "xld", "xle", "xlg", "xli", "xln", "xlo", "xlp", "xls", "xlu", "xly", "xma", "xmb", "xmc", "xmd", "xme", "xmf", "xmg", "xmh", "xmj", "xmk", "xml", "xmm", "xmn", "xmo", "xmp", "xmq", "xmr", "xms", "xmt", "xmu", "xmv", "xmw", "xmx", "xmy", "xmz", "xna", "xnb", "xnd", "xng", "xnh", "xni", "xnj", "xnk", "xnm", "xnn", "xno", "xnq", "xnr", "xns", "xnt", "xnu", "xny", "xnz", "xoc", "xod", "xog", "xoi", "xok", "xom", "xon", "xoo", "xop", "xor", "xow", "xpa", "xpb", "xpc", "xpd", "xpe", "xpf", "xpg", "xph", "xpi", "xpj", "xpk", "xpl", "xpm", "xpn", "xpo", "xpp", "xpq", "xpr", "xps", "xpt", "xpu", "xpv", "xpw", "xpx", "xpy", "xpz", "xqa", "xqt", "xra", "xrb", "xrd", "xre", "xrg", "xri", "xrm", "xrn", "xrq", "xrr", "xrt", "xru", "xrw", "xsa", "xsb", "xsc", "xsd", "xse", "xsh", "xsi", "xsj", "xsl", "xsm", "xsn", "xso", "xsp", "xsq", "xsr", "xss", "xsu", "xsv", "xsy", "xta", "xtb", "xtc", "xtd", "xte", "xtg", "xth", "xti", "xtj", "xtl", "xtm", "xtn", "xto", "xtp", "xtq", "xtr", "xts", "xtt", "xtu", "xtv", "xtw", "xty", "xtz", "xua", "xub", "xud", "xug", "xuj", "xul", "xum", "xun", "xuo", "xup", "xur", "xut", "xuu", "xve", "xvi", "xvn", "xvo", "xvs", "xwa", "xwc", "xwd", "xwe", "xwg", "xwj", "xwk", "xwl", "xwo", "xwr", "xwt", "xww", "xxb", "xxk", "xxm", "xxr", "xxt", "xya", "xyb", "xyj", "xyk", "xyl", "xyt", "xyy", "xzh", "xzm", "xzp"], + ["yi", "yo", "yaa", "yab", "yac", "yad", "yae", "yaf", "yag", "yah", "yai", "yaj", "yak", "yal", "yam", "yan", "yao", "yap", "yaq", "yar", "yas", "yat", "yau", "yav", "yaw", "yax", "yay", "yaz", "yba", "ybb", "ybd", "ybe", "ybh", "ybi", "ybj", "ybk", "ybl", "ybm", "ybn", "ybo", "ybx", "yby", "ych", "ycl", "ycn", "ycp", "yda", "ydd", "yde", "ydg", "ydk", "yds", "yea", "yec", "yee", "yei", "yej", "yel", "yen", "yer", "yes", "yet", "yeu", "yev", "yey", "yga", "ygi", "ygl", "ygm", "ygp", "ygr", "ygs", "ygu", "ygw", "yha", "yhd", "yhl", "yhs", "yia", "yif", "yig", "yih", "yii", "yij", "yik", "yil", "yim", "yin", "yip", "yiq", "yir", "yis", "yit", "yiu", "yiv", "yix", "yiy", "yiz", "yka", "ykg", "yki", "ykk", "ykl", "ykm", "ykn", "yko", "ykr", "ykt", "yku", "yky", "yla", "ylb", "yle", "ylg", "yli", "yll", "ylm", "yln", "ylo", "ylr", "ylu", "yly", "yma", "ymb", "ymc", "ymd", "yme", "ymg", "ymh", "ymi", "ymk", "yml", "ymm", "ymn", "ymo", "ymp", "ymq", "ymr", "yms", "ymt", "ymx", "ymz", "yna", "ynd", "yne", "yng", "ynh", "ynk", "ynl", "ynn", "yno", "ynq", "yns", "ynu", "yob", "yog", "yoi", "yok", "yol", "yom", "yon", "yos", "yot", "yox", "yoy", "ypa", "ypb", "ypg", "yph", "ypk", "ypm", "ypn", "ypo", "ypp", "ypz", "yra", "yrb", "yre", "yri", "yrk", "yrl", "yrm", "yrn", "yro", "yrs", "yrw", "yry", "ysc", "ysd", "ysg", "ysl", "ysm", "ysn", "yso", "ysp", "ysr", "yss", "ysy", "yta", "ytl", "ytp", "ytw", "yty", "yua", "yub", "yuc", "yud", "yue", "yuf", "yug", "yui", "yuj", "yuk", "yul", "yum", "yun", "yup", "yuq", "yur", "yut", "yuu", "yuw", "yux", "yuy", "yuz", "yva", "yvt", "ywa", "ywg", "ywl", "ywn", "ywq", "ywr", "ywt", "ywu", "yww", "yxa", "yxg", "yxl", "yxm", "yxu", "yxy", "yyr", "yyu", "yyz", "yzg", "yzk"], + ["za", "zh", "zu", "zaa", "zab", "zac", "zad", "zae", "zaf", "zag", "zah", "zai", "zaj", "zak", "zal", "zam", "zao", "zap", "zaq", "zar", "zas", "zat", "zau", "zav", "zaw", "zax", "zay", "zaz", "zba", "zbc", "zbe", "zbl", "zbt", "zbu", "zbw", "zca", "zch", "zdj", "zea", "zeg", "zeh", "zen", "zga", "zgb", "zgh", "zgm", "zgn", "zgr", "zhb", "zhd", "zhi", "zhn", "zhw", "zhx", "zia", "zib", "zik", "zil", "zim", "zin", "zir", "ziw", "ziz", "zka", "zkb", "zkd", "zkg", "zkh", "zkk", "zkn", "zko", "zkp", "zkr", "zkt", "zku", "zkv", "zkz", "zla", "zle", "zlj", "zlm", "zln", "zlq", "zls", "zlw", "zma", "zmb", "zmc", "zmd", "zme", "zmf", "zmg", "zmh", "zmi", "zmj", "zmk", "zml", "zmm", "zmn", "zmo", "zmp", "zmq", "zmr", "zms", "zmt", "zmu", "zmv", "zmw", "zmx", "zmy", "zmz", "zna", "znd", "zne", "zng", "znk", "zns", "zoc", "zoh", "zom", "zoo", "zoq", "zor", "zos", "zpa", "zpb", "zpc", "zpd", "zpe", "zpf", "zpg", "zph", "zpi", "zpj", "zpk", "zpl", "zpm", "zpn", "zpo", "zpp", "zpq", "zpr", "zps", "zpt", "zpu", "zpv", "zpw", "zpx", "zpy", "zpz", "zqe", "zra", "zrg", "zrn", "zro", "zrp", "zrs", "zsa", "zsk", "zsl", "zsm", "zsr", "zsu", "zte", "ztg", "ztl", "ztm", "ztn", "ztp", "ztq", "zts", "ztt", "ztu", "ztx", "zty", "zua", "zuh", "zum", "zun", "zuy", "zwa", "zxx", "zyb", "zyg", "zyj", "zyn", "zyp", "zza", "zzj"] +]; +var LangUtil = /** @class */ (function () { + function LangUtil() { + } + /* Determine if given string is a valid BCP 47 string */ + LangUtil.isBcp47 = function (langStr) { + return /^(([a-zA-Z]{2,3}(-[a-zA-Z](-[a-zA-Z]{3}){0,2})?|[a-zA-Z]{4}|[a-zA-Z]{5,8})(-[a-zA-Z]{4})?(-([a-zA-Z]{2}|[0-9]{3}))?(-([0-9a-zA-Z]{5,8}|[0-9][a-zA-Z]{3}))*(-[0-9a-wy-zA-WY-Z](-[a-zA-Z0-9]{2,8})+)*(-x(-[a-zA-Z0-9]{1,8})+)?|x(-[a-zA-Z0-9]{1,8})+|(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE|art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))$/.test(langStr); + }; + LangUtil.validPrimaryLang = function (langStr) { + var primary = langStr.toLowerCase(); + if (primary.includes("-")) { + primary = primary.split("-")[0]; + } + if (!primary.match(/[a-z]{2,3}/)) + return false; + // qaa..qtz + if (primary.length === 3 + && primary.charAt(0) === "q" + && primary.charCodeAt(1) >= 97 && primary.charCodeAt(1) <= 116 + && primary.charCodeAt(2) >= 97 && primary.charCodeAt(2) <= 122) { + } + return validPrimaryLangs[primary.charCodeAt(0) - 97].includes(primary); + }; + LangUtil.matchPrimaryLang = function (lang1, lang2) { + var primary1 = lang1; + if (primary1.includes("-")) { + primary1 = primary1.split("-")[0]; + } + var primary2 = lang2; + if (primary2.includes("-")) { + primary2 = primary2.split("-")[0]; + } + return primary1.toLowerCase() === primary2.toLowerCase(); + }; + return LangUtil; +}()); +exports.LangUtil = LangUtil; + + +/***/ }), + +/***/ "./src/v2/checker/accessibility/util/legacy.ts": +/*!*****************************************************!*\ + !*** ./src/v2/checker/accessibility/util/legacy.ts ***! + \*****************************************************/ +/***/ (function(__unused_webpack_module, exports, __webpack_require__) { + + +/****************************************************************************** + Copyright:: 2020- IBM, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NodeWalker = exports.RPTUtil = void 0; +var CacheUtil_1 = __webpack_require__(/*! ../../../../v4/util/CacheUtil */ "./src/v4/util/CacheUtil.ts"); +var ARIADefinitions_1 = __webpack_require__(/*! ../../../aria/ARIADefinitions */ "./src/v2/aria/ARIADefinitions.ts"); +var ARIAMapper_1 = __webpack_require__(/*! ../../../aria/ARIAMapper */ "./src/v2/aria/ARIAMapper.ts"); +var DOMWalker_1 = __webpack_require__(/*! ../../../dom/DOMWalker */ "./src/v2/dom/DOMWalker.ts"); +var VisUtil_1 = __webpack_require__(/*! ../../../dom/VisUtil */ "./src/v2/dom/VisUtil.ts"); +var fragment_1 = __webpack_require__(/*! ./fragment */ "./src/v2/checker/accessibility/util/fragment.ts"); +var CSSUtil_1 = __webpack_require__(/*! ../../../../v4/util/CSSUtil */ "./src/v4/util/CSSUtil.ts"); +var DOMUtil_1 = __webpack_require__(/*! ../../../dom/DOMUtil */ "./src/v2/dom/DOMUtil.ts"); +var DOMMapper_1 = __webpack_require__(/*! ../../../dom/DOMMapper */ "./src/v2/dom/DOMMapper.ts"); +var RPTUtil = /** @class */ (function () { + function RPTUtil() { + } + RPTUtil.isDefinedAriaAttributeAtIndex = function (ele, index) { + var attrName = ele.attributes[index].name; + return RPTUtil.isDefinedAriaAttribute(ele, attrName); + }; + /** + * this method returns user-defined aria attribute name from dom + * @param ele element + * @returns user defined aria attributes + */ + RPTUtil.getUserDefinedAriaAttributes = function (elem) { + var ariaAttributes = []; + var domAttributes = elem.attributes; + if (domAttributes) { + for (var i = 0; i < domAttributes.length; i++) { + var attrName = domAttributes[i].name.trim().toLowerCase(); + var isAria = attrName.substring(0, 5) === 'aria-'; + if (isAria) + ariaAttributes.push(attrName); + } + } + return ariaAttributes; + }; + /** + * this method returns user-defined html attribute name from dom + * @param ele element + * @returns user defined html attributes + */ + RPTUtil.getUserDefinedHtmlAttributes = function (elem) { + var htmlAttributes = []; + var domAttributes = elem.attributes; + if (domAttributes) { + for (var i = 0; i < domAttributes.length; i++) { + var attrName = domAttributes[i].name.trim().toLowerCase(); + var isAria = attrName.substring(0, 5) === 'aria-'; + if (!isAria) + htmlAttributes.push(attrName); + } + } + return htmlAttributes; + }; + /** + * this method returns user-defined aria attribute name-value pair from dom + * @param ele element + * @returns user defined aria attributes + */ + RPTUtil.getUserDefinedAriaAttributeNameValuePairs = function (elem) { + var ariaAttributes = []; + var domAttributes = elem.attributes; + if (domAttributes) { + for (var i = 0; i < domAttributes.length; i++) { + var attrName = domAttributes[i].name.trim().toLowerCase(); + var attrValue = elem.getAttribute(attrName); + if (attrValue === '') + attrValue = null; + var isAria = attrName.substring(0, 5) === 'aria-'; + if (isAria) + ariaAttributes.push({ name: attrName, value: attrValue }); + } + } + return ariaAttributes; + }; + /** + * this method returns user-defined html attribute name-value pair from dom + * @param ele element + * @returns user defined html attributes + */ + RPTUtil.getUserDefinedHtmlAttributeNameValuePairs = function (elem) { + var htmlAttributes = []; + var domAttributes = elem.attributes; + if (domAttributes) { + for (var i = 0; i < domAttributes.length; i++) { + var attrName = domAttributes[i].name.trim().toLowerCase(); + var attrValue = elem.getAttribute(attrName); + if (attrValue === '') + attrValue = null; + var isAria = attrName.substring(0, 5) === 'aria-'; + if (!isAria) + htmlAttributes.push({ name: attrName, value: attrValue }); + } + } + return htmlAttributes; + }; + /** + * This method handles implicit aria definitions, for example, an input with checked is equivalent to aria-checked="true" + */ + RPTUtil.getAriaAttribute = function (ele, attributeName) { + // If the attribute is defined, it takes precedence + var retVal = ele.getAttribute(attributeName); + if (ele.hasAttribute(attributeName) && retVal.trim() === "") { //"" is treated as false, so we need return it before the below check + return retVal; + } + // Then determine implicit values from other attributes + if (!retVal) { + var tag = ele.nodeName.toLowerCase(); + if (attributeName in RPTUtil.ariaAttributeImplicitMappings) { + if (tag in RPTUtil.ariaAttributeImplicitMappings[attributeName]) { + retVal = RPTUtil.ariaAttributeImplicitMappings[attributeName][tag]; + if (typeof (retVal) === "function") { + retVal = retVal(ele); + } + } + else if ("*" in RPTUtil.ariaAttributeImplicitMappings[attributeName]) { + retVal = RPTUtil.ariaAttributeImplicitMappings[attributeName]["*"]; + if (typeof (retVal) === "function") { + retVal = retVal(ele); + } + } + } + } + // Check role-based defaults + if (!retVal) { + var role = ARIAMapper_1.ARIAMapper.nodeToRole(ele); + if (role in RPTUtil.ariaAttributeRoleDefaults && attributeName in RPTUtil.ariaAttributeRoleDefaults[role]) { + retVal = RPTUtil.ariaAttributeRoleDefaults[role][attributeName]; + if (typeof (retVal) === "function") { + retVal = retVal(ele); + } + } + } + // Still not defined? Check global defaults + if (!retVal && attributeName in RPTUtil.ariaAttributeGlobalDefaults) { + retVal = RPTUtil.ariaAttributeGlobalDefaults[attributeName]; + } + return retVal; + }; + RPTUtil.wordCount = function (str) { + str = str.trim(); + if (str.length === 0) + return 0; + return str.split(/\s+/g).length; + }; + /** + * Note that this only detects if the element itself is in the tab order. + * However, this element may delegate focus to another element via aria-activedescendant. + * Also, focus varies by browser... sticking to things that are focusable on Chrome and Firefox. + */ + RPTUtil.isTabbable = function (element) { + // Using https://allyjs.io/data-tables/focusable.html + // Handle the explicit cases first + if (!VisUtil_1.VisUtil.isNodeVisible(element)) + return false; + if (element.hasAttribute("tabindex")) { + return parseInt(element.getAttribute("tabindex")) >= 0; + } + // Explicit cases handled - now the implicit + var nodeName = element.nodeName.toLowerCase(); + if (nodeName in RPTUtil.tabTagMap) { + var retVal = RPTUtil.tabTagMap[nodeName]; + if (typeof (retVal) === "function") { + retVal = retVal(element); + } + return retVal; + } + else { + return false; + } + }; + /** + * a target is en element that accept a pointer action (click or touch) + * + */ + RPTUtil.isTarget = function (element) { + if (!element) + return false; + if (element.hasAttribute("tabindex") || RPTUtil.isTabbable(element)) + return true; + var roles = RPTUtil.getRoles(element, true); + if (!roles && roles.length === 0) + return false; + var tagProperty = RPTUtil.getElementAriaProperty(element); + var allowedRoles = RPTUtil.getAllowedAriaRoles(element, tagProperty); + if (!allowedRoles || allowedRoles.length === 0) + return false; + var parent = element.parentElement; + // datalist, fieldset, optgroup, etc. may be just used for grouping purpose, so go up to the parent + while (parent && roles.some(function (role) { return role === 'group'; })) + parent = parent.parentElement; + if (parent && (parent.hasAttribute("tabindex") || RPTUtil.isTabbable(parent))) { + var target_roles_1 = ["listitem", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "switch", "treeitem"]; + if (allowedRoles.includes('any') || roles.some(function (role) { return target_roles_1.includes(role); })) + return true; + } + return false; + }; + /** + * a target is en element that accept a pointer action (click or touch) + * a target is a browser default if it's a native widget (no user defined role) without user style + */ + RPTUtil.isTargetBrowserDefault = function (element) { + if (!element) + return false; + // user defained widget + var roles = RPTUtil.getRoles(element, false); + if (roles && roles.length > 0) + return false; + // no user style to space control size, including use of font + var styles = (0, CSSUtil_1.getDefinedStyles)(element); + if (styles['line-height'] || styles['height'] || styles['width'] || styles['min-height'] || styles['min-width'] + || styles['font-size'] || styles['margin-top'] || styles['margin-bottom'] || styles['margin-left'] || styles['margin-right']) + return false; + return true; + }; + /** + * an "inline" CSS display property tells the element to fit itself on the same line. An 'inline' element's width and height are ignored. + * some element has default inline property, such as , + * most formatting elements inherent inline property, such as , , , + * other inline elements: