markuplint icon indicating copy to clipboard operation
markuplint copied to clipboard

Implement HTML-AAM §4.1 compliant accessible name computation

Open Copilot opened this issue 9 months ago • 2 comments

This PR reimplements accessible name computation to align with the HTML Accessibility API Mappings (HTML-AAM) specification §4.1 "Accessible Name Computations By HTML Element."

Problem

Previously, Markuplint used the dom-accessibility-api library for accessible name computations across all elements. However, according to HTML-AAM §4.1, certain HTML elements should compute their accessible names only when they possess aria-label or aria-labelledby attributes. Without these attributes, each element should follow specific conditions to determine their accessible names.

Solution

Conditional Application of accname Library

  • Apply the dom-accessibility-api library exclusively to elements that have:
    • aria-label attribute
    • aria-labelledby attribute
    • role attribute (explicit ARIA roles)
    • style attribute (for proper visibility handling)

Element-Specific Accessible Name Logic

Implement custom logic for elements without the above attributes, adhering to HTML-AAM §4.1:

  • <img>: Use the alt attribute, fallback to title
  • <input>: Derive name from associated <label> elements or fallback to placeholder
  • <textarea> and <select>: Use associated <label> elements
  • <button>: Use the element's text content
  • <a> and headings (<h1>-<h6>): Use text content
  • <table>: Use <caption> element
  • <fieldset>: Use <legend> element
  • Other elements: Return empty string unless they have ARIA attributes

Key Implementation Details

// Before: Always used dom-accessibility-api
const name = computeAccessibleName(el);

// After: Conditional based on HTML-AAM §4.1
if (hasAriaNameAttributes(el)) {
    return computeAccessibleName(el); // Use accname library
}
return getElementSpecificAccessibleName(el); // Use element-specific logic

The implementation properly handles:

  • Label association for form elements (searches both element root and document scope)
  • Hidden elements (aria-hidden, hidden attribute, CSS styles)
  • Nested text content extraction while excluding hidden elements
  • Backward compatibility with existing behavior

Benefits

  • ✅ Standards Compliance: Accessible name computation now aligns with HTML-AAM specification
  • ✅ Improved Accuracy: More precise accessibility validations by considering element-specific naming conditions
  • ✅ Performance Optimization: Reduced unnecessary computations by applying accname library only when relevant attributes are present

Testing

Added comprehensive test suite covering:

  • Elements with aria-label/aria-labelledby (should use accname library)
  • Element-specific logic for all supported HTML elements
  • Label association scenarios for form controls
  • Hidden element handling
  • Edge cases and backward compatibility

All existing tests continue to pass, ensuring no regressions.

Fixes #2437.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot avatar Jun 22 '25 01:06 Copilot

@copilot

Could you include https://github.com/markuplint/markuplint/issues/1478 as well?

YusukeHirao avatar Jun 22 '25 05:06 YusukeHirao

@copilot

Could you include https://github.com/markuplint/markuplint/issues/1478 as well? ...

I've included issue #1478 by implementing a new rule no-conflicting-accessible-name that detects when multiple accessible name sources are provided for an element (e.g., both <label> and aria-labelledby). The rule follows the same pattern as the example you provided and helps prevent developer confusion about which accessible name will be used. See commit c0c0ba6.

Copilot avatar Jun 22 '25 05:06 Copilot