Skip to content

Releases: ryersondmp/sa11y

Sa11y 5.0.9

Choose a tag to compare

@adamchaboryk adamchaboryk released this 30 Jul 14:38
c3f700e

Bug fix: Invalid headers queryselector for malformed IDs.

Sa11y 5.0.8

Choose a tag to compare

@adamchaboryk adamchaboryk released this 16 Jun 14:46
7505a80

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

Choose a tag to compare

@adamchaboryk adamchaboryk released this 12 Jun 19:04
a21bdcc

Improvements

  • Enhanced embedded content checks: Added support for the <embed> tag.
  • Implemented Intl.Segmenter to 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 escapeHTML utility function to support downstream formatting needs.

Bug fixes

  • Configuration crash fix: Resolved an issue causing errors to throw when the MISSING_ALT rule was explicitly disabled. (#164 — Thank you @itmaybejj)

Sa11y 5.0.6

Choose a tag to compare

@adamchaboryk adamchaboryk released this 05 Jun 20:11
4a41bbf

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

Choose a tag to compare

@adamchaboryk adamchaboryk released this 29 May 16:28

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

Choose a tag to compare

@adamchaboryk adamchaboryk released this 29 May 16:10
74b6bc1

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

Choose a tag to compare

@adamchaboryk adamchaboryk released this 21 Apr 04:12
ef9ba67

Fix logic issue with HIDDEN_FOCUSABLE test.

Sa11y 5.0.2

Choose a tag to compare

@adamchaboryk adamchaboryk released this 20 Apr 23:46
  • 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 pushResult helper to standardize pushing results to State.results and migrate callers to use it.
  • Refactor all ruleset files to utilize pushResult helper, 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 svg fallbacks.
  • Adds CI tweaks (CodeQL config file and publish workflow permissions).

Sa11y 5.0

Choose a tag to compare

@adamchaboryk adamchaboryk released this 17 Apr 01:47
fce9f64

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

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 to true to activate the ruleset.
  • langOfPartsCache: Set to true to 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_VALID and META_LANG_SUGGEST.

  • New link checks: The LINK_UNPRONOUNCEABLE rule 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_BUTTON rule compliments the QA_IN_PAGE_LINK check 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_DOI check 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.
  • 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_NAME and QA_IN_PAGE_LINK

  • New test: TABLES_INVALID_HEADERS_REF evaluates whether the headers attribute within a table contains an invalid reference.

  • New test: ARIA_INPUT_FIELD_NAME evaluates 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, and stripHTMLtags. 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 panelPosition prop to ensure proper visual placement of control panel.
  • Bug fix regarding altPlaceholder prop.
  • 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

Choose a tag to compare

@adamchaboryk adamchaboryk released this 23 Dec 18:59

Bug fixes

  • Fixed an issue where SVG colour filters used an incorrect unit for width (100vh100vw). 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.