Releases: ryersondmp/sa11y
Release list
Sa11y 5.0.9
Bug fix: Invalid headers queryselector for malformed IDs.
Sa11y 5.0.8
Bug fixes
- Turning off one rule no longer accidentally stops other rules from running on the same element.
- False positive fix in fake list detection.
Sa11y 5.0.7
Improvements
- Enhanced embedded content checks: Added support for the
<embed>tag. - Implemented
Intl.Segmenterto significantly improve the detection of redundant words in alt text (e.g. "image of") for languages that do not use spaces (e.g., Japanese, Chinese). This check now looks for the presence of these redundant words in the first two words of a string, or the last word (e.g. alt="magnifying glass icon"). Thanks @Michael-Nesci!! - Enhanced various internal utility functions to be more fault-tolerant against unexpected edge cases.
- Reintroduced the
escapeHTMLutility function to support downstream formatting needs.
Bug fixes
- Configuration crash fix: Resolved an issue causing errors to throw when the
MISSING_ALTrule was explicitly disabled. (#164 — Thank you @itmaybejj)
Sa11y 5.0.6
Improved i18n support
All language files have been refactored to organize strings into distinct categories: ui, tooltip, and rulesets. This architectural update allows developers to programmatically import ruleset strings from other languages, drastically improving the accuracy of localized validation. This change is 100% backwards compatible with zero breaking changes.
Example
The example below demonstrates how importing Ukrainian ruleset strings enhances audit accuracy, such as detecting localized stopwords in alt text. While the user interface displays in English, the validation engine will scan for both English and Ukrainian placeholder words.
<link rel="stylesheet" href="../../src/css/sa11y.css" />
<script type="module">
import { Sa11y, Lang } from '../../src/js/sa11y.js';
import Sa11yLangUa from '../../src/lang/ua.js';
import Sa11yLangEn from '../../src/lang/en.js';
// Instantiate
const mergedStrings = { ...(Sa11yLangEn.strings), ...(Sa11yLangUa.ruleset) };
Lang.addI18n(mergedStrings);
const sa11y = new Sa11y({});
</script>Acknowledgements
Many thanks to @itmaybejj and @brianteeman (#162).
Sa11y 5.0.5
Bug fix
Reverting change where PUA characters are excluded from accessible name computation. PUA characters do not render in Sa11y's control panel or Outline panel, which may cause confusion.
Sa11y 5.0.4
New features
- New unpronounceable heading detection – Detects empty or meaningless headings (e.g.,
<h2>?</h2>) that lack accessible name content. - Expanded PDF link detection – Added /pdf/ to PDF source patterns for more comprehensive detection of PDF-linked content.
- Enhanced suspicious alt text detection – Added "portrait" to the suspicious alt word list. (#158, thanks @brianteeman)
Bug fixes
- Fixed alt text validation for CJK text – Unicode scripts (Chinese, Japanese, Korean) are now properly validated, eliminating false positives for space-less word structures and full-width punctuation.
- Fixed link validation false positives – Links with aria-label and decorative images no longer trigger incorrect warnings. (#159, thanks @matzesa)
- Fixed PDF link detection – Corrected invalid link sources preventing QA_PDF test from executing (#157, thanks @itmaybejj)
- Restored PUA characters in accessible name computation – Private Use Area (PUA) characters are no longer incorrectly removed during name calculation.
Thanks to @Michael-Nesci for finding bugs and testing!
Sa11y 5.0.3
Fix logic issue with HIDDEN_FOCUSABLE test.
Sa11y 5.0.2
- Addresses a serious TypeError in 5.0.1.
Developer changes
These changes consolidate logic and reduce duplication.
- Fix
Lang.sprintf()argument handling and adjust regex behaviour. - Initialize and centralize many constants (stopwords, placeholder sets, link/file type patterns, click/new-window regexes).
- Introduce
pushResulthelper to standardize pushing results toState.resultsand migrate callers to use it. - Refactor all ruleset files to utilize
pushResulthelper, significantly consolidating code. - Improve contrast preview rendering by setting styles on the preview element instead of inline HTML building.
- Change annotation insertion order to prefer link/button targets before
svgfallbacks. - Adds CI tweaks (CodeQL config file and publish workflow permissions).
Sa11y 5.0
This release features a significant refactor focused on XSS prevention, performance optimization, and reduced bundle size. The update enhances existing accessibility checks and includes a first-of-its-kind experimental Language Detection check, powered by the on-device Language Detector API (currently exclusive to Google Chrome).
New experimental checks for language detection
This new ruleset leverages on-device AI to automatically detect and validate the language of your content, ensuring it matches a web page’s language declaration. This feature helps identify issues pertaining to the following WCAG success criteria:
- Language of Page (Level A): Verifies that the primary language declared in the document matches the actual content on the page.
- Language of Parts (Level AA): Scans individual text blocks and image alt text to ensure shifts in language are correctly identified via the lang attribute.
Demo
- Try: the bookmarklet on any webpage.
- View: CodePen demo.
Implementation notes
- This is an experimental browser API and is only available in Chrome at this time.
- For better performance, Sa11y will only run this check once on a page. It will stop scanning remaining element nodes after the first detection. If significant text changes are detected on the page, Sa11y will trigger a fresh scan.
- This feature utilizes a built-in browser Language Detector API. All language analysis is performed locally on your machine, ensuring your page content is never sent to a cloud server or external third party for processing.
Disclaimer: Please note that AI-detection is not 100% accurate and is intended only to flag glaring issues for manual review; results should always be verified by a human.
Enabling this check
This experimental check is off by default. To start using these rules, update your configuration with the following properties:
langOfPartsPlugin: Set totrueto activate the ruleset.langOfPartsCache: Set totrueto enable smarter caching. This prevents redundant scans by storing results for up to 200 URLs and only triggers a fresh analysis if it detects a change in page text, declared language, or previously flagged elements.
Ruleset & logic improvements
-
Page language attribute validation: New ruleset that validates language codes by leveraging the browser’s native Intl.DisplayNames API for improved accuracy over standard string matching. The logic detects and flags invalid declarations, such as those using underscores (e.g., en_US), and provides the normalized string as a recommended suggestion for the user to implement. To ensure stability across all environments, the check includes a regex-based fallback for legacy browsers. New test names include:
META_LANG_VALIDandMETA_LANG_SUGGEST. -
New link checks: The
LINK_UNPRONOUNCEABLErule has been introduced as a standalone check to differentiate links containing only symbols (e.g., ., >, ?) from truly empty tags. This new rule provides a specific tooltip suggesting the link may be a copy-paste error and should either be deleted or given descriptive text. By separating this logic, the audit now offers clearer, more actionable feedback for non-alphanumeric content that screen readers cannot meaningfully process.- The
LINK_MAYBE_BUTTONrule compliments theQA_IN_PAGE_LINKcheck to ensure that broken same page links which resemble a scripted UI control will receive a more appropriate error description. - Improved DOI detection: The
LINK_DOIcheck has been improved to detect link text matching Digital Object Identifiers (DOIs) that lack a prefix. The updated regex identifies strings starting with 10.xxxx, ensuring that academic and technical references are properly captured even when formatted as plain text within a link.
- The
-
Alt text quality checks: Improved detection of nonsensical alt text strings.
- Added untitled image, unnamed, and copy to alt placeholder check for English language files.
- When checking for placeholder stop words, special characters are filtered out to improve accuracy of check (in addition to numbers).
- Alt text that have no spaces, are at least 15 characters, and contain at least 3 dashes/underscores will be flagged as an error.
- New warning-level check that builds upon existing logic for identifying auto-generated alt text. This separate condition flags instances where there is a lower confidence that the text is machine-generated, but it still warrants a manual review. An image will now trigger a warning if its alt text meets any of the following:
- Numeric strings: Consists of 5 or more digits (e.g., 12345).
- Excessive delimiters: Contains more than 3 hyphens (-) or underscores (_).
-
Contrast module improvements:
- Now supports the display-p3 color gamut.
- Contrast logic for gradients has been refined; warnings are now only triggered if a specific color stop fails, significantly reducing false positives.
- Transparent foreground colours and disabled elements are now ignored.
- Performance has also been improved through optimizing the RGBA color conversion logic, reducing computational overhead. Addition of caching and memoization of various functions to prevent redundant DOM traversals for the same elements.
- Added contrast checking support for slotted elements by traversing the flattened DOM tree to accurately detect background colours across Shadow DOM boundaries.
- Contrast check will ignore nodes that only contain non-text characters or visual separators (like / or \ or |).
-
Minimized false positives:
- Minor logic fixes to reduce false positives around fake heading detection.
- Warnings for justified and small text can now be dismissed all.
- Minimize false positives for test
LABELS_ARIA_LABEL_INPUT. - Reduced false positives around fake list detection, and improved detection of potential fake list patterns.
-
Changes to “Good” annotations: The tooltip text for images and links flagged as "Good" will now display "Review" instead. While these elements may technically have alt text or accessible names, the quality of that content still requires human verification. This change prompts developers and authors to ensure the descriptions are actually meaningful, rather than just present.
-
Improved tooltip verbiage for
LINK_IDENTICAL_NAMEandQA_IN_PAGE_LINK -
New test:
TABLES_INVALID_HEADERS_REFevaluates whether the headers attribute within a table contains an invalid reference. -
New test:
ARIA_INPUT_FIELD_NAMEevaluates ARIA-based input or switch fields for an accessible name.
Targeted element exclusion
Developers can now programmatically ignore elements by specific test keys. This provides more granular control, allowing you to exclude specific elements per check, without silencing all other accessibility alerts for that same item. Using the prop ignoreByTest.
For example:
ignoreByTest: {
QA_FAKE_HEADING: 'p.ignore strong',
},Security Improvements
- XSS hardening: Mitigated cross-site scripting by replacing unsafe HTML parsing with secure DOM APIs and literal text rendering.
- Improved data privacy: Hashing is used to hide the values used for dismiss keys, ensuring that data pulled from page elements remains private.
- Code Quality: Integrated CodeQL analysis workflows and custom configuration files for automated security scanning.
Developer changes
Significant refactoring of the main Sa11y class now includes dedicated state management for better stability and cleaner code architecture.
- Utility methods: All utility functions exposed are now exposed as methods for custom implementations.
- Sanitization: Raw text strings passed via custom checks now receive automatic HTML sanitization. However, it’s highly recommended to always use
Lang.sprintf()when passing in tooltip content for custom checks. - New prop: New prop
paragraphIgnore: 'table p',to add exclusions for specific paragraph<p>elements. - Removed functions: Removed
decodeHTML,escapeHTML, andstripHTMLtags. These utilities are now obsolete as Sa11y leverages native DOM APIs and literal text rendering for improved security. - Migration of tippy.js to floating-ui: Tippy.js was archived November 2024. Migration to floating-ui improves performance and reduces total bundle size by almost 10%.
Bug fixes
- Added fallback for
panelPositionprop to ensure proper visual placement of control panel. - Bug fix regarding
altPlaceholderprop. - Adjusted readability thresholds and closed score gaps for more consistent analysis.
- Improvements to accessible name calculation.
- Console error message now includes Sa11y’s configuration to help debug.
- Fixed a memory leak.
- Fallback icon added to the Images panel when an image’s source is invalid, or an SVG, or is less than 1px in width or height.
Translations
New Tamil translation. Many thanks to Jayaseelan Samuel @smartsw33t!
Acknowledgments
Many thanks to @itmaybejj for his contributions to this release!
Sa11y 4.4.1
Bug fixes
- Fixed an issue where SVG colour filters used an incorrect unit for width (
100vh→100vw). Thanks to @LadySolveig! - Replaced the multi-step tritanopia SVG filter with a single color-matrix implementation to prevent Firefox ESR from rasterizing the page and causing text blur.
- Consolidated the
resetColourFilters()function and removed duplicate logic. - Fixed a state restoration bug where toggling Sa11y’s main button while a colour filter was active did not correctly return the page to its normal state.