Programmatic access to the WAI-ARIA 1.2 Roles Model specification with comprehensive role definitions, HTML element mappings, and ARIA property data.
—
Registry of HTML elements with their reserved status for ARIA role assignment. This helps determine which elements can accept role attributes and which have restrictions on role usage.
Retrieves the DOM definition for a specific HTML element.
/**
* Get DOM definition for an HTML element
* @param key - HTML element name
* @returns DOM definition object or null if not found
*/
dom.get(key: string): DOMDefinition | null;Usage Examples:
import { dom } from "aria-query";
// Check if div is reserved for roles
const divDef = dom.get('div');
console.log(divDef.reserved); // false
// Check if base element is reserved
const baseDef = dom.get('base');
console.log(baseDef.reserved); // true
// Check button element
const buttonDef = dom.get('button');
console.log(buttonDef.reserved); // false
// Check if an element exists in the registry
const customDef = dom.get('custom-element');
console.log(customDef); // nullDetermines if an HTML element exists in the DOM registry.
/**
* Check if an HTML element exists in the DOM registry
* @param key - HTML element name to check
* @returns True if element exists, false otherwise
*/
dom.has(key: string): boolean;Returns an array of all HTML element names in the registry.
/**
* Get array of all HTML element names
* @returns Array of element name strings
*/
dom.keys(): Array<string>;Returns an array of all DOM definition objects.
/**
* Get array of all DOM definition objects
* @returns Array of DOMDefinition objects
*/
dom.values(): Array<DOMDefinition>;Returns all elements as an array of [name, definition] tuples.
/**
* Get all elements as [name, definition] tuples
* @returns Array of [string, DOMDefinition] tuples
*/
dom.entries(): Array<[string, DOMDefinition]>;Executes a function for each element definition.
/**
* Execute function for each element definition
* @param fn - Function to execute for each element
* @param thisArg - Optional this context for the function
*/
dom.forEach(fn: (definition: DOMDefinition, name: string, entries: Array<[string, DOMDefinition]>) => void, thisArg?: any): void;Usage Examples:
import { dom } from "aria-query";
// Find all reserved elements
const reservedElements = [];
dom.forEach((definition, name) => {
if (definition.reserved) {
reservedElements.push(name);
}
});
// Find all non-reserved elements that can accept roles
const roleAcceptingElements = dom.keys().filter(name => {
const def = dom.get(name);
return !def.reserved;
});
// Check specific elements for role compatibility
const elementsToCheck = ['div', 'span', 'section', 'head', 'script'];
const roleCompatibility = {};
elementsToCheck.forEach(elementName => {
if (dom.has(elementName)) {
roleCompatibility[elementName] = !dom.get(elementName).reserved;
}
});Elements that cannot accept ARIA role attributes due to their semantic meaning or technical constraints:
const reservedElements = [
'base', // Document metadata
'col', // Table column
'colgroup', // Table column group
'head', // Document head
'html', // Root element
'link', // External resource link
'meta', // Document metadata
'noembed', // Fallback content
'noscript', // Script fallback
'param', // Object parameter
'picture', // Responsive image container
'script', // Script element
'source', // Media resource
'style', // Style information
'title', // Document title
'track' // Text track for media
];Elements that can accept ARIA role attributes (most HTML elements):
const nonReservedElements = [
// Semantic elements
'main', 'nav', 'section', 'article', 'aside', 'header', 'footer',
// Content elements
'div', 'span', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
// Form elements
'form', 'input', 'button', 'select', 'textarea', 'fieldset', 'legend',
// List elements
'ul', 'ol', 'li', 'dl', 'dt', 'dd',
// Table elements
'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td',
// Media elements
'img', 'audio', 'video', 'canvas',
// And many more...
];import { dom } from "aria-query";
/**
* Check if an element can accept a role attribute
* @param elementName - HTML element name
* @returns True if element can accept roles, false if reserved
*/
function canAcceptRole(elementName) {
if (!dom.has(elementName)) {
// Unknown elements can typically accept roles
return true;
}
const definition = dom.get(elementName);
return !definition.reserved;
}
// Examples
console.log(canAcceptRole('div')); // true
console.log(canAcceptRole('button')); // true
console.log(canAcceptRole('script')); // false
console.log(canAcceptRole('head')); // falseimport { dom } from "aria-query";
/**
* Validate role assignment for accessibility linting
* @param elementName - HTML element name
* @param roleName - ARIA role being assigned
* @returns Validation result with warnings
*/
function validateRoleAssignment(elementName, roleName) {
const result = {
valid: true,
warnings: []
};
if (dom.has(elementName)) {
const definition = dom.get(elementName);
if (definition.reserved) {
result.valid = false;
result.warnings.push(
`Element "${elementName}" is reserved and cannot accept role "${roleName}"`
);
}
}
return result;
}import { dom } from "aria-query";
// Categorize all elements by reserved status
function categorizeElements() {
const categories = {
reserved: [],
available: []
};
dom.forEach((definition, name) => {
if (definition.reserved) {
categories.reserved.push(name);
} else {
categories.available.push(name);
}
});
return categories;
}
const elementCategories = categorizeElements();
console.log('Reserved elements:', elementCategories.reserved.length);
console.log('Available for roles:', elementCategories.available.length);
// Alternative implementation using direct iteration
function categorizeElementsAlt() {
const categories = { reserved: [], available: [] };
for (const [name, definition] of dom) {
if (definition.reserved) {
categories.reserved.push(name);
} else {
categories.available.push(name);
}
}
return categories;
}// DOM element definition structure
interface DOMDefinition {
/** Whether the element is reserved and cannot accept ARIA role attributes */
reserved: boolean;
}
// Type aliases for collections
type DOMDefinitionTuple = [string, DOMDefinition];
type DOMDefinitions = Array<DOMDefinitionTuple>;
// Union type of all HTML element names supported
type TAriaQueryHTMLElement =
'a' | 'abbr' | 'acronym' | 'address' | 'applet' | 'area' | 'article' | 'aside' |
'audio' | 'b' | 'base' | 'bdi' | 'bdo' | 'big' | 'blink' | 'blockquote' |
'body' | 'br' | 'button' | 'canvas' | 'caption' | 'center' | 'cite' | 'code' |
'col' | 'colgroup' | 'content' | 'data' | 'datalist' | 'dd' | 'del' | 'details' |
'dfn' | 'dialog' | 'dir' | 'div' | 'dl' | 'dt' | 'em' | 'embed' | 'fieldset' |
'figcaption' | 'figure' | 'font' | 'footer' | 'form' | 'frame' | 'frameset' |
'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'head' | 'header' | 'hgroup' |
'hr' | 'html' | 'i' | 'iframe' | 'img' | 'input' | 'ins' | 'kbd' | 'keygen' |
'label' | 'legend' | 'li' | 'link' | 'main' | 'map' | 'mark' | 'marquee' |
'menu' | 'menuitem' | 'meta' | 'meter' | 'nav' | 'noembed' | 'noscript' |
'object' | 'ol' | 'optgroup' | 'option' | 'output' | 'p' | 'param' | 'picture' |
'pre' | 'progress' | 'q' | 'rp' | 'rt' | 'rtc' | 'ruby' | 's' | 'samp' |
'script' | 'section' | 'select' | 'small' | 'source' | 'spacer' | 'span' |
'strike' | 'strong' | 'style' | 'sub' | 'summary' | 'sup' | 'table' | 'tbody' |
'td' | 'textarea' | 'tfoot' | 'th' | 'thead' | 'time' | 'title' | 'tr' |
'track' | 'tt' | 'u' | 'ul' | 'var' | 'video' | 'wbr' | 'xmp';Install with Tessl CLI
npx tessl i tessl/npm-aria-query