1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-28 08:37:35 +00:00

LibWeb: Move ARIA-related code into the Web::ARIA namespace

ARIA has its own spec and is not part of the DOM spec, which is what the
Web::DOM namespace is for (https://www.w3.org/TR/wai-aria-1.2/).

This allows us to stay closer to the spec with function names and don't
have to add the word "ARIA" to identifiers constantly - the namespace
now provides that clarity.
This commit is contained in:
Linus Groh 2023-01-28 22:23:16 +00:00
parent 8414734a2d
commit 8556d47240
61 changed files with 179 additions and 180 deletions

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/ARIA/ARIAMixin.h>
#include <LibWeb/ARIA/Roles.h>
#include <LibWeb/Infra/CharacterTypes.h>
namespace Web::ARIA {
// https://www.w3.org/TR/wai-aria-1.2/#introroles
Optional<Role> ARIAMixin::role_or_default() const
{
// 1. Use the rules of the host language to detect that an element has a role attribute and to identify the attribute value string for it.
auto role_string = role();
// 2. Separate the attribute value string for that attribute into a sequence of whitespace-free substrings by separating on whitespace.
auto role_list = role_string.split_view(Infra::is_ascii_whitespace);
// 3. Compare the substrings to all the names of the non-abstract WAI-ARIA roles. Case-sensitivity of the comparison inherits from the case-sensitivity of the host language.
for (auto const& role_name : role_list) {
// 4. Use the first such substring in textual order that matches the name of a non-abstract WAI-ARIA role.
auto role = role_from_string(role_name);
if (!role.has_value())
continue;
if (is_non_abstract_role(*role))
return *role;
}
// https://www.w3.org/TR/wai-aria-1.2/#document-handling_author-errors_roles
// If the role attribute contains no tokens matching the name of a non-abstract WAI-ARIA role, the user agent MUST treat the element as if no role had been provided.
// https://www.w3.org/TR/wai-aria-1.2/#implicit_semantics
return default_role();
}
// https://www.w3.org/TR/wai-aria-1.2/#global_states
bool ARIAMixin::has_global_aria_attribute() const
{
return !aria_atomic().is_null()
|| !aria_busy().is_null()
|| !aria_controls().is_null()
|| !aria_current().is_null()
|| !aria_described_by().is_null()
|| !aria_details().is_null()
|| !aria_disabled().is_null()
|| !aria_drop_effect().is_null()
|| !aria_error_message().is_null()
|| !aria_flow_to().is_null()
|| !aria_grabbed().is_null()
|| !aria_has_popup().is_null()
|| !aria_hidden().is_null()
|| !aria_invalid().is_null()
|| !aria_key_shortcuts().is_null()
|| !aria_label().is_null()
|| !aria_labelled_by().is_null()
|| !aria_live().is_null()
|| !aria_owns().is_null()
|| !aria_relevant().is_null()
|| !aria_role_description().is_null();
}
}

View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/DeprecatedFlyString.h>
#include <LibWeb/ARIA/Roles.h>
#include <LibWeb/WebIDL/ExceptionOr.h>
namespace Web::ARIA {
class ARIAMixin {
public:
virtual ~ARIAMixin() = default;
virtual DeprecatedString role() const = 0;
virtual WebIDL::ExceptionOr<void> set_role(DeprecatedString const&) = 0;
virtual DeprecatedString aria_active_descendant() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_active_descendant(DeprecatedString const&) = 0;
virtual DeprecatedString aria_atomic() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_atomic(DeprecatedString const&) = 0;
virtual DeprecatedString aria_auto_complete() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_auto_complete(DeprecatedString const&) = 0;
virtual DeprecatedString aria_busy() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_busy(DeprecatedString const&) = 0;
virtual DeprecatedString aria_checked() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_checked(DeprecatedString const&) = 0;
virtual DeprecatedString aria_col_count() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_col_count(DeprecatedString const&) = 0;
virtual DeprecatedString aria_col_index() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_col_index(DeprecatedString const&) = 0;
virtual DeprecatedString aria_col_span() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_col_span(DeprecatedString const&) = 0;
virtual DeprecatedString aria_controls() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_controls(DeprecatedString const&) = 0;
virtual DeprecatedString aria_current() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_current(DeprecatedString const&) = 0;
virtual DeprecatedString aria_described_by() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_described_by(DeprecatedString const&) = 0;
virtual DeprecatedString aria_details() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_details(DeprecatedString const&) = 0;
virtual DeprecatedString aria_drop_effect() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_drop_effect(DeprecatedString const&) = 0;
virtual DeprecatedString aria_error_message() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_error_message(DeprecatedString const&) = 0;
virtual DeprecatedString aria_disabled() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_disabled(DeprecatedString const&) = 0;
virtual DeprecatedString aria_expanded() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_expanded(DeprecatedString const&) = 0;
virtual DeprecatedString aria_flow_to() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_flow_to(DeprecatedString const&) = 0;
virtual DeprecatedString aria_grabbed() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_grabbed(DeprecatedString const&) = 0;
virtual DeprecatedString aria_has_popup() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_has_popup(DeprecatedString const&) = 0;
virtual DeprecatedString aria_hidden() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_hidden(DeprecatedString const&) = 0;
virtual DeprecatedString aria_invalid() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_invalid(DeprecatedString const&) = 0;
virtual DeprecatedString aria_key_shortcuts() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_key_shortcuts(DeprecatedString const&) = 0;
virtual DeprecatedString aria_label() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_label(DeprecatedString const&) = 0;
virtual DeprecatedString aria_labelled_by() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_labelled_by(DeprecatedString const&) = 0;
virtual DeprecatedString aria_level() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_level(DeprecatedString const&) = 0;
virtual DeprecatedString aria_live() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_live(DeprecatedString const&) = 0;
virtual DeprecatedString aria_modal() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_modal(DeprecatedString const&) = 0;
virtual DeprecatedString aria_multi_line() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_multi_line(DeprecatedString const&) = 0;
virtual DeprecatedString aria_multi_selectable() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_multi_selectable(DeprecatedString const&) = 0;
virtual DeprecatedString aria_orientation() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_orientation(DeprecatedString const&) = 0;
virtual DeprecatedString aria_owns() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_owns(DeprecatedString const&) = 0;
virtual DeprecatedString aria_placeholder() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_placeholder(DeprecatedString const&) = 0;
virtual DeprecatedString aria_pos_in_set() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_pos_in_set(DeprecatedString const&) = 0;
virtual DeprecatedString aria_pressed() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_pressed(DeprecatedString const&) = 0;
virtual DeprecatedString aria_read_only() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_read_only(DeprecatedString const&) = 0;
virtual DeprecatedString aria_relevant() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_relevant(DeprecatedString const&) = 0;
virtual DeprecatedString aria_required() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_required(DeprecatedString const&) = 0;
virtual DeprecatedString aria_role_description() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_role_description(DeprecatedString const&) = 0;
virtual DeprecatedString aria_row_count() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_row_count(DeprecatedString const&) = 0;
virtual DeprecatedString aria_row_index() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_row_index(DeprecatedString const&) = 0;
virtual DeprecatedString aria_row_span() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_row_span(DeprecatedString const&) = 0;
virtual DeprecatedString aria_selected() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_selected(DeprecatedString const&) = 0;
virtual DeprecatedString aria_set_size() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_set_size(DeprecatedString const&) = 0;
virtual DeprecatedString aria_sort() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_sort(DeprecatedString const&) = 0;
virtual DeprecatedString aria_value_max() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_value_max(DeprecatedString const&) = 0;
virtual DeprecatedString aria_value_min() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_value_min(DeprecatedString const&) = 0;
virtual DeprecatedString aria_value_now() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_value_now(DeprecatedString const&) = 0;
virtual DeprecatedString aria_value_text() const = 0;
virtual WebIDL::ExceptionOr<void> set_aria_value_text(DeprecatedString const&) = 0;
// https://www.w3.org/TR/html-aria/#docconformance
virtual Optional<Role> default_role() const { return {}; };
Optional<Role> role_or_default() const;
// https://www.w3.org/TR/wai-aria-1.2/#tree_exclusion
virtual bool exclude_from_accessibility_tree() const = 0;
// https://www.w3.org/TR/wai-aria-1.2/#tree_inclusion
virtual bool include_in_accessibility_tree() const = 0;
bool has_global_aria_attribute() const;
protected:
ARIAMixin() = default;
};
}

View file

@ -0,0 +1,53 @@
// https://www.w3.org/TR/wai-aria-1.2/#ARIAMixin
interface mixin ARIAMixin {
attribute DOMString? role;
attribute DOMString? ariaAtomic;
attribute DOMString? ariaAutoComplete;
attribute DOMString? ariaBusy;
attribute DOMString? ariaChecked;
attribute DOMString? ariaColCount;
attribute DOMString? ariaColIndex;
attribute DOMString? ariaColSpan;
attribute DOMString? ariaCurrent;
attribute DOMString? ariaDisabled;
attribute DOMString? ariaExpanded;
attribute DOMString? ariaHasPopup;
attribute DOMString? ariaHidden;
attribute DOMString? ariaInvalid;
attribute DOMString? ariaKeyShortcuts;
attribute DOMString? ariaLabel;
attribute DOMString? ariaLevel;
attribute DOMString? ariaLive;
attribute DOMString? ariaModal;
attribute DOMString? ariaMultiLine;
attribute DOMString? ariaMultiSelectable;
attribute DOMString? ariaOrientation;
attribute DOMString? ariaPlaceholder;
attribute DOMString? ariaPosInSet;
attribute DOMString? ariaPressed;
attribute DOMString? ariaReadOnly;
attribute DOMString? ariaRequired;
attribute DOMString? ariaRoleDescription;
attribute DOMString? ariaRowCount;
attribute DOMString? ariaRowIndex;
attribute DOMString? ariaRowSpan;
attribute DOMString? ariaSelected;
attribute DOMString? ariaSetSize;
attribute DOMString? ariaSort;
attribute DOMString? ariaValueMax;
attribute DOMString? ariaValueMin;
attribute DOMString? ariaValueNow;
attribute DOMString? ariaValueText;
};

View file

@ -0,0 +1,172 @@
/*
* Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/GenericShorthands.h>
#include <LibWeb/ARIA/Roles.h>
namespace Web::ARIA {
StringView role_name(Role role)
{
switch (role) {
#define __ENUMERATE_ARIA_ROLE(name) \
case Role::name: \
return #name##sv;
ENUMERATE_ARIA_ROLES
#undef __ENUMERATE_ARIA_ROLE
default:
VERIFY_NOT_REACHED();
}
}
Optional<Role> role_from_string(StringView role_name)
{
#define __ENUMERATE_ARIA_ROLE(name) \
if (role_name.equals_ignoring_case(#name##sv)) \
return Role::name;
ENUMERATE_ARIA_ROLES
#undef __ENUMERATE_ARIA_ROLE
return {};
}
// https://www.w3.org/TR/wai-aria-1.2/#abstract_roles
bool is_abstract_role(Role role)
{
return first_is_one_of(role,
Role::command,
Role::composite,
Role::input,
Role::landmark,
Role::range,
Role::roletype,
Role::section,
Role::sectionhead,
Role::select,
Role::structure,
Role::widget,
Role::window);
}
// https://www.w3.org/TR/wai-aria-1.2/#widget_roles
bool is_widget_role(Role role)
{
return first_is_one_of(role,
Role::button,
Role::checkbox,
Role::gridcell,
Role::link,
Role::menuitem,
Role::menuitemcheckbox,
Role::option,
Role::progressbar,
Role::radio,
Role::scrollbar,
Role::searchbox,
Role::separator, // TODO: Only when focusable
Role::slider,
Role::spinbutton,
Role::switch_,
Role::tab,
Role::tabpanel,
Role::textbox,
Role::treeitem,
Role::combobox,
Role::grid,
Role::listbox,
Role::menu,
Role::menubar,
Role::radiogroup,
Role::tablist,
Role::tree,
Role::treegrid);
}
// https://www.w3.org/TR/wai-aria-1.2/#document_structure_roles
bool is_document_structure_role(Role role)
{
return first_is_one_of(role,
Role::application,
Role::article,
Role::blockquote,
Role::caption,
Role::cell,
Role::columnheader,
Role::definition,
Role::deletion,
Role::directory,
Role::document,
Role::emphasis,
Role::feed,
Role::figure,
Role::generic,
Role::group,
Role::heading,
Role::img,
Role::insertion,
Role::list,
Role::listitem,
Role::math,
Role::meter,
Role::none,
Role::note,
Role::paragraph,
Role::presentation,
Role::row,
Role::rowgroup,
Role::rowheader,
Role::separator, // TODO: Only when not focusable
Role::strong,
Role::subscript,
Role::table,
Role::term,
Role::time,
Role::toolbar,
Role::tooltip);
}
// https://www.w3.org/TR/wai-aria-1.2/#landmark_roles
bool is_landmark_role(Role role)
{
return first_is_one_of(role,
Role::banner,
Role::complementary,
Role::contentinfo,
Role::form,
Role::main,
Role::navigation,
Role::region,
Role::search);
}
// https://www.w3.org/TR/wai-aria-1.2/#live_region_roles
bool is_live_region_role(Role role)
{
return first_is_one_of(role,
Role::alert,
Role::log,
Role::marquee,
Role::status,
Role::timer);
}
// https://www.w3.org/TR/wai-aria-1.2/#window_roles
bool is_windows_role(Role role)
{
return first_is_one_of(role,
Role::alertdialog,
Role::dialog);
}
bool is_non_abstract_role(Role role)
{
return is_widget_role(role)
|| is_document_structure_role(role)
|| is_landmark_role(role)
|| is_live_region_role(role)
|| is_windows_role(role);
}
}

View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/DeprecatedFlyString.h>
namespace Web::ARIA {
#define ENUMERATE_ARIA_ROLES \
__ENUMERATE_ARIA_ROLE(alert) \
__ENUMERATE_ARIA_ROLE(alertdialog) \
__ENUMERATE_ARIA_ROLE(application) \
__ENUMERATE_ARIA_ROLE(article) \
__ENUMERATE_ARIA_ROLE(banner) \
__ENUMERATE_ARIA_ROLE(blockquote) \
__ENUMERATE_ARIA_ROLE(button) \
__ENUMERATE_ARIA_ROLE(caption) \
__ENUMERATE_ARIA_ROLE(cell) \
__ENUMERATE_ARIA_ROLE(checkbox) \
__ENUMERATE_ARIA_ROLE(code) \
__ENUMERATE_ARIA_ROLE(columnheader) \
__ENUMERATE_ARIA_ROLE(combobox) \
__ENUMERATE_ARIA_ROLE(command) \
__ENUMERATE_ARIA_ROLE(complementary) \
__ENUMERATE_ARIA_ROLE(composite) \
__ENUMERATE_ARIA_ROLE(contentinfo) \
__ENUMERATE_ARIA_ROLE(definition) \
__ENUMERATE_ARIA_ROLE(deletion) \
__ENUMERATE_ARIA_ROLE(dialog) \
__ENUMERATE_ARIA_ROLE(directory) \
__ENUMERATE_ARIA_ROLE(document) \
__ENUMERATE_ARIA_ROLE(emphasis) \
__ENUMERATE_ARIA_ROLE(feed) \
__ENUMERATE_ARIA_ROLE(figure) \
__ENUMERATE_ARIA_ROLE(form) \
__ENUMERATE_ARIA_ROLE(generic) \
__ENUMERATE_ARIA_ROLE(grid) \
__ENUMERATE_ARIA_ROLE(gridcell) \
__ENUMERATE_ARIA_ROLE(group) \
__ENUMERATE_ARIA_ROLE(heading) \
__ENUMERATE_ARIA_ROLE(img) \
__ENUMERATE_ARIA_ROLE(input) \
__ENUMERATE_ARIA_ROLE(insertion) \
__ENUMERATE_ARIA_ROLE(landmark) \
__ENUMERATE_ARIA_ROLE(link) \
__ENUMERATE_ARIA_ROLE(list) \
__ENUMERATE_ARIA_ROLE(listbox) \
__ENUMERATE_ARIA_ROLE(listitem) \
__ENUMERATE_ARIA_ROLE(log) \
__ENUMERATE_ARIA_ROLE(main) \
__ENUMERATE_ARIA_ROLE(marquee) \
__ENUMERATE_ARIA_ROLE(math) \
__ENUMERATE_ARIA_ROLE(meter) \
__ENUMERATE_ARIA_ROLE(menu) \
__ENUMERATE_ARIA_ROLE(menubar) \
__ENUMERATE_ARIA_ROLE(menuitem) \
__ENUMERATE_ARIA_ROLE(menuitemcheckbox) \
__ENUMERATE_ARIA_ROLE(menuitemradio) \
__ENUMERATE_ARIA_ROLE(navigation) \
__ENUMERATE_ARIA_ROLE(none) \
__ENUMERATE_ARIA_ROLE(note) \
__ENUMERATE_ARIA_ROLE(option) \
__ENUMERATE_ARIA_ROLE(paragraph) \
__ENUMERATE_ARIA_ROLE(presentation) \
__ENUMERATE_ARIA_ROLE(progressbar) \
__ENUMERATE_ARIA_ROLE(radio) \
__ENUMERATE_ARIA_ROLE(radiogroup) \
__ENUMERATE_ARIA_ROLE(range) \
__ENUMERATE_ARIA_ROLE(region) \
__ENUMERATE_ARIA_ROLE(roletype) \
__ENUMERATE_ARIA_ROLE(row) \
__ENUMERATE_ARIA_ROLE(rowgroup) \
__ENUMERATE_ARIA_ROLE(rowheader) \
__ENUMERATE_ARIA_ROLE(scrollbar) \
__ENUMERATE_ARIA_ROLE(search) \
__ENUMERATE_ARIA_ROLE(searchbox) \
__ENUMERATE_ARIA_ROLE(section) \
__ENUMERATE_ARIA_ROLE(sectionhead) \
__ENUMERATE_ARIA_ROLE(select) \
__ENUMERATE_ARIA_ROLE(separator) \
__ENUMERATE_ARIA_ROLE(slider) \
__ENUMERATE_ARIA_ROLE(spinbutton) \
__ENUMERATE_ARIA_ROLE(status) \
__ENUMERATE_ARIA_ROLE(strong) \
__ENUMERATE_ARIA_ROLE(structure) \
__ENUMERATE_ARIA_ROLE(subscript) \
__ENUMERATE_ARIA_ROLE(superscript) \
__ENUMERATE_ARIA_ROLE(switch_) \
__ENUMERATE_ARIA_ROLE(tab) \
__ENUMERATE_ARIA_ROLE(table) \
__ENUMERATE_ARIA_ROLE(tablist) \
__ENUMERATE_ARIA_ROLE(tabpanel) \
__ENUMERATE_ARIA_ROLE(term) \
__ENUMERATE_ARIA_ROLE(textbox) \
__ENUMERATE_ARIA_ROLE(time) \
__ENUMERATE_ARIA_ROLE(timer) \
__ENUMERATE_ARIA_ROLE(toolbar) \
__ENUMERATE_ARIA_ROLE(tooltip) \
__ENUMERATE_ARIA_ROLE(tree) \
__ENUMERATE_ARIA_ROLE(treegrid) \
__ENUMERATE_ARIA_ROLE(treeitem) \
__ENUMERATE_ARIA_ROLE(widget) \
__ENUMERATE_ARIA_ROLE(window)
enum class Role {
#define __ENUMERATE_ARIA_ROLE(name) name,
ENUMERATE_ARIA_ROLES
#undef __ENUMERATE_ARIA_ROLE
};
StringView role_name(Role);
Optional<Role> role_from_string(StringView role_name);
bool is_abstract_role(Role);
bool is_widget_role(Role);
bool is_document_structure_role(Role);
bool is_landmark_role(Role);
bool is_live_region_role(Role);
bool is_windows_role(Role);
bool is_non_abstract_role(Role);
}