diff options
Diffstat (limited to 'Userland/Libraries')
57 files changed, 976 insertions, 1 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 605441e5ec..0d0f987e5e 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -74,6 +74,9 @@ set(SOURCES DOM/AbstractRange.cpp DOM/Attr.cpp DOM/Attr.idl + DOM/ARIAMixin.cpp + DOM/ARIAMixin.idl + DOM/ARIARoleNames.cpp DOM/CDATASection.cpp DOM/CharacterData.cpp DOM/CharacterData.idl diff --git a/Userland/Libraries/LibWeb/DOM/ARIAMixin.cpp b/Userland/Libraries/LibWeb/DOM/ARIAMixin.cpp new file mode 100644 index 0000000000..f2a49568e4 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/ARIAMixin.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/DOM/ARIAMixin.h> +#include <LibWeb/DOM/ARIARoleNames.h> +#include <LibWeb/Infra/CharacterTypes.h> + +namespace Web::DOM { + +// https://www.w3.org/TR/wai-aria-1.2/#introroles +FlyString 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 : role_list) { + // 4. Use the first such substring in textual order that matches the name of a non-abstract WAI-ARIA role. + if (ARIARoleNames::is_non_abstract_aria_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(); +} + +} diff --git a/Userland/Libraries/LibWeb/DOM/ARIAMixin.h b/Userland/Libraries/LibWeb/DOM/ARIAMixin.h new file mode 100644 index 0000000000..ec97d69f11 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/ARIAMixin.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/FlyString.h> +#include <LibWeb/WebIDL/ExceptionOr.h> + +namespace Web::DOM { + +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 FlyString default_role() const { return {}; }; + + FlyString role_or_default() const; + +protected: + ARIAMixin() = default; +}; + +} diff --git a/Userland/Libraries/LibWeb/DOM/ARIAMixin.idl b/Userland/Libraries/LibWeb/DOM/ARIAMixin.idl new file mode 100644 index 0000000000..f608e238a9 --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/ARIAMixin.idl @@ -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; +}; diff --git a/Userland/Libraries/LibWeb/DOM/ARIARoleNames.cpp b/Userland/Libraries/LibWeb/DOM/ARIARoleNames.cpp new file mode 100644 index 0000000000..afd709610e --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/ARIARoleNames.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/DOM/ARIARoleNames.h> + +namespace Web::DOM::ARIARoleNames { + +#define __ENUMERATE_ARIA_ROLE(name) FlyString name; +ENUMERATE_ARIA_ROLES +#undef __ENUMERATE_ARIA_ROLE + +[[gnu::constructor]] static void initialize() +{ + static bool s_initialized = false; + if (s_initialized) + return; + +#define __ENUMERATE_ARIA_ROLE(name) name = #name; + ENUMERATE_ARIA_ROLES +#undef __ENUMERATE_ARIA_ROLE + + // Special case for C++ keyword + switch_ = "switch"; + s_initialized = true; +} + +// https://www.w3.org/TR/wai-aria-1.2/#abstract_roles +bool is_abstract_aria_role(FlyString const& role) +{ + return role.is_one_of( + ARIARoleNames::command, + ARIARoleNames::composite, + ARIARoleNames::input, + ARIARoleNames::landmark, + ARIARoleNames::range, + ARIARoleNames::roletype, + ARIARoleNames::section, + ARIARoleNames::sectionhead, + ARIARoleNames::select, + ARIARoleNames::structure, + ARIARoleNames::widget, + ARIARoleNames::window); +} + +// https://www.w3.org/TR/wai-aria-1.2/#widget_roles +bool is_widget_aria_role(FlyString const& role) +{ + return role.to_lowercase().is_one_of( + ARIARoleNames::button, + ARIARoleNames::checkbox, + ARIARoleNames::gridcell, + ARIARoleNames::link, + ARIARoleNames::menuitem, + ARIARoleNames::menuitemcheckbox, + ARIARoleNames::option, + ARIARoleNames::progressbar, + ARIARoleNames::radio, + ARIARoleNames::scrollbar, + ARIARoleNames::searchbox, + ARIARoleNames::separator, // TODO: Only when focusable + ARIARoleNames::slider, + ARIARoleNames::spinbutton, + ARIARoleNames::switch_, + ARIARoleNames::tab, + ARIARoleNames::tabpanel, + ARIARoleNames::textbox, + ARIARoleNames::treeitem, + ARIARoleNames::combobox, + ARIARoleNames::grid, + ARIARoleNames::listbox, + ARIARoleNames::menu, + ARIARoleNames::menubar, + ARIARoleNames::radiogroup, + ARIARoleNames::tablist, + ARIARoleNames::tree, + ARIARoleNames::treegrid); +} + +// https://www.w3.org/TR/wai-aria-1.2/#document_structure_roles +bool is_document_structure_aria_role(FlyString const& role) +{ + return role.to_lowercase().is_one_of( + ARIARoleNames::application, + ARIARoleNames::article, + ARIARoleNames::blockquote, + ARIARoleNames::caption, + ARIARoleNames::cell, + ARIARoleNames::columnheader, + ARIARoleNames::definition, + ARIARoleNames::deletion, + ARIARoleNames::directory, + ARIARoleNames::document, + ARIARoleNames::emphasis, + ARIARoleNames::feed, + ARIARoleNames::figure, + ARIARoleNames::generic, + ARIARoleNames::group, + ARIARoleNames::heading, + ARIARoleNames::img, + ARIARoleNames::insertion, + ARIARoleNames::list, + ARIARoleNames::listitem, + ARIARoleNames::math, + ARIARoleNames::meter, + ARIARoleNames::none, + ARIARoleNames::note, + ARIARoleNames::paragraph, + ARIARoleNames::presentation, + ARIARoleNames::row, + ARIARoleNames::rowgroup, + ARIARoleNames::rowheader, + ARIARoleNames::separator, // TODO: Only when not focusable + ARIARoleNames::strong, + ARIARoleNames::subscript, + ARIARoleNames::table, + ARIARoleNames::term, + ARIARoleNames::time, + ARIARoleNames::toolbar, + ARIARoleNames::tooltip); +} + +// https://www.w3.org/TR/wai-aria-1.2/#landmark_roles +bool is_landmark_aria_role(FlyString const& role) +{ + return role.to_lowercase().is_one_of( + ARIARoleNames::banner, + ARIARoleNames::complementary, + ARIARoleNames::contentinfo, + ARIARoleNames::form, + ARIARoleNames::main, + ARIARoleNames::navigation, + ARIARoleNames::region, + ARIARoleNames::search); +} + +// https://www.w3.org/TR/wai-aria-1.2/#live_region_roles +bool is_live_region_aria_role(FlyString const& role) +{ + return role.to_lowercase().is_one_of( + ARIARoleNames::alert, + ARIARoleNames::log, + ARIARoleNames::marquee, + ARIARoleNames::status, + ARIARoleNames::timer); +} + +// https://www.w3.org/TR/wai-aria-1.2/#window_roles +bool is_windows_aria_role(FlyString const& role) +{ + return role.to_lowercase().is_one_of( + ARIARoleNames::alertdialog, + ARIARoleNames::dialog); +} + +bool is_non_abstract_aria_role(FlyString const& role) +{ + return is_widget_aria_role(role) + || is_document_structure_aria_role(role) + || is_landmark_aria_role(role) + || is_live_region_aria_role(role) + || is_windows_aria_role(role); +} + +} diff --git a/Userland/Libraries/LibWeb/DOM/ARIARoleNames.h b/Userland/Libraries/LibWeb/DOM/ARIARoleNames.h new file mode 100644 index 0000000000..36d310643e --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/ARIARoleNames.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022, Jonah Shafran <jonahshafran@gmail.com> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/FlyString.h> + +namespace Web::DOM::ARIARoleNames { + +#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) + +#define __ENUMERATE_ARIA_ROLE(name) extern FlyString name; +ENUMERATE_ARIA_ROLES +#undef __ENUMERATE_ARIA_ROLE + +bool is_abstract_aria_role(FlyString const&); +bool is_widget_aria_role(FlyString const&); +bool is_document_structure_aria_role(FlyString const&); +bool is_landmark_aria_role(FlyString const&); +bool is_live_region_aria_role(FlyString const&); +bool is_windows_aria_role(FlyString const&); + +bool is_non_abstract_aria_role(FlyString const&); + +} diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 4b3c7ebbc3..a31d9f2343 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -11,6 +11,7 @@ #include <LibWeb/Bindings/ElementPrototype.h> #include <LibWeb/CSS/CSSStyleDeclaration.h> #include <LibWeb/CSS/StyleComputer.h> +#include <LibWeb/DOM/ARIAMixin.h> #include <LibWeb/DOM/Attr.h> #include <LibWeb/DOM/ChildNode.h> #include <LibWeb/DOM/NamedNodeMap.h> @@ -40,7 +41,8 @@ struct ScrollIntoViewOptions : public ScrollOptions { class Element : public ParentNode , public ChildNode<Element> - , public NonDocumentTypeChildNode<Element> { + , public NonDocumentTypeChildNode<Element> + , public ARIAMixin { WEB_PLATFORM_OBJECT(Element, ParentNode); public: @@ -177,6 +179,72 @@ public: // https://w3c.github.io/csswg-drafts/cssom-view-1/#dom-element-scrollintoview ErrorOr<void> scroll_into_view(Optional<Variant<bool, ScrollIntoViewOptions>> = {}); + // https://www.w3.org/TR/wai-aria-1.2/#ARIAMixin +#define ARIA_IMPL(name, attribute) \ + DeprecatedString name() const override \ + { \ + return get_attribute(attribute); \ + } \ + \ + WebIDL::ExceptionOr<void> set_##name(DeprecatedString const& value) override \ + { \ + TRY(set_attribute(attribute, value)); \ + return {}; \ + } + + // https://www.w3.org/TR/wai-aria-1.2/#accessibilityroleandproperties-correspondence + ARIA_IMPL(role, "role"); + ARIA_IMPL(aria_active_descendant, "aria-activedescendant"); + ARIA_IMPL(aria_atomic, "aria-atomic"); + ARIA_IMPL(aria_auto_complete, "aria-autocomplete"); + ARIA_IMPL(aria_busy, "aria-busy"); + ARIA_IMPL(aria_checked, "aria-checked"); + ARIA_IMPL(aria_col_count, "aria-colcount"); + ARIA_IMPL(aria_col_index, "aria-colindex"); + ARIA_IMPL(aria_col_span, "aria-colspan"); + ARIA_IMPL(aria_controls, "aria-controls"); + ARIA_IMPL(aria_current, "aria-current"); + ARIA_IMPL(aria_described_by, "aria-describedby"); + ARIA_IMPL(aria_details, "aria-details"); + ARIA_IMPL(aria_drop_effect, "aria-dropeffect"); + ARIA_IMPL(aria_error_message, "aria-errormessage"); + ARIA_IMPL(aria_disabled, "aria-disabled"); + ARIA_IMPL(aria_expanded, "aria-expanded"); + ARIA_IMPL(aria_flow_to, "aria-flowto"); + ARIA_IMPL(aria_grabbed, "aria-grabbed"); + ARIA_IMPL(aria_has_popup, "aria-haspopup"); + ARIA_IMPL(aria_hidden, "aria-hidden"); + ARIA_IMPL(aria_invalid, "aria-invalid"); + ARIA_IMPL(aria_key_shortcuts, "aria-keyshortcuts"); + ARIA_IMPL(aria_label, "aria-label"); + ARIA_IMPL(aria_labelled_by, "aria-labelledby"); + ARIA_IMPL(aria_level, "aria-level"); + ARIA_IMPL(aria_live, "aria-live"); + ARIA_IMPL(aria_modal, "aria-modal"); + ARIA_IMPL(aria_multi_line, "aria-multiline"); + ARIA_IMPL(aria_multi_selectable, "aria-multiselectable"); + ARIA_IMPL(aria_orientation, "aria-orientation"); + ARIA_IMPL(aria_owns, "aria-owns"); + ARIA_IMPL(aria_placeholder, "aria-placeholder"); + ARIA_IMPL(aria_pos_in_set, "aria-posinset"); + ARIA_IMPL(aria_pressed, "aria-pressed"); + ARIA_IMPL(aria_read_only, "aria-readonly"); + ARIA_IMPL(aria_relevant, "aria-relevant"); + ARIA_IMPL(aria_required, "aria-required"); + ARIA_IMPL(aria_role_description, "aria-roledescription"); + ARIA_IMPL(aria_row_count, "aria-rowcount"); + ARIA_IMPL(aria_row_index, "aria-rowindex"); + ARIA_IMPL(aria_row_span, "aria-rowspan"); + ARIA_IMPL(aria_selected, "aria-selected"); + ARIA_IMPL(aria_set_size, "aria-setsize"); + ARIA_IMPL(aria_sort, "aria-sort"); + ARIA_IMPL(aria_value_max, "aria-valuemax"); + ARIA_IMPL(aria_value_min, "aria-valuemin"); + ARIA_IMPL(aria_value_now, "aria-valuenow"); + ARIA_IMPL(aria_value_text, "aria-valuetext"); + +#undef ARIA_IMPL + protected: Element(Document&, DOM::QualifiedName); virtual void initialize(JS::Realm&) override; diff --git a/Userland/Libraries/LibWeb/DOM/Element.idl b/Userland/Libraries/LibWeb/DOM/Element.idl index 46a98c7145..c152206aa2 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.idl +++ b/Userland/Libraries/LibWeb/DOM/Element.idl @@ -1,5 +1,6 @@ #import <CSS/CSSStyleDeclaration.idl> #import <DOM/Attr.idl> +#import <DOM/ARIAMixin.idl> #import <DOM/ChildNode.idl> #import <DOM/DOMTokenList.idl> #import <DOM/InnerHTML.idl> @@ -83,3 +84,5 @@ interface Element : Node { Element includes ParentNode; Element includes ChildNode; Element includes InnerHTML; +// https://www.w3.org/TR/wai-aria-1.2/#idl_element +Element includes ARIAMixin; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp index 07e0bc2a15..073c160df1 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLAnchorElement.h> #include <LibWeb/HTML/Window.h> @@ -84,4 +85,13 @@ i32 HTMLAnchorElement::default_tab_index_value() const return 0; } +FlyString HTMLAnchorElement::default_role() const +{ + // https://www.w3.org/TR/html-aria/#el-a-no-href + if (!href().is_null()) + return DOM::ARIARoleNames::link; + // https://www.w3.org/TR/html-aria/#el-a + return DOM::ARIARoleNames::generic; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h index 60e6080bea..3356a21400 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h @@ -50,6 +50,8 @@ private: { queue_an_element_task(source, move(steps)); } + + virtual FlyString default_role() const override; }; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.cpp index e1a720288d..05bf062466 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLAreaElement.h> #include <LibWeb/HTML/Window.h> @@ -42,4 +43,13 @@ i32 HTMLAreaElement::default_tab_index_value() const return 0; } +FlyString HTMLAreaElement::default_role() const +{ + // https://www.w3.org/TR/html-aria/#el-area-no-href + if (!href().is_null()) + return DOM::ARIARoleNames::link; + // https://www.w3.org/TR/html-aria/#el-area + return DOM::ARIARoleNames::generic; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h index 840d5a16cc..80398dd0a6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h @@ -39,6 +39,8 @@ private: { queue_an_element_task(source, move(steps)); } + + virtual FlyString default_role() const override; }; } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h index 9da891799d..e1ff7613cb 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> #include <LibWeb/HTML/WindowEventHandlers.h> @@ -22,6 +23,9 @@ public: virtual void parse_attribute(FlyString const&, DeprecatedString const&) override; virtual void apply_presentational_hints(CSS::StyleProperties&) const override; + // https://www.w3.org/TR/html-aria/#el-body + virtual FlyString default_role() const override { return DOM::ARIARoleNames::generic; }; + private: HTMLBodyElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h index f1a27b773e..64c8033526 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/FormAssociatedElement.h> #include <LibWeb/HTML/HTMLElement.h> @@ -53,6 +54,9 @@ public: // https://html.spec.whatwg.org/multipage/forms.html#category-label virtual bool is_labelable() const override { return true; } + // https://www.w3.org/TR/html-aria/#el-button + virtual FlyString default_role() const override { return DOM::ARIARoleNames::button; } + private: HTMLButtonElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h index da9548124d..c2e0a6ad67 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDataElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLDataElement final : public HTMLElement { public: virtual ~HTMLDataElement() override; + // https://www.w3.org/TR/html-aria/#el-data + virtual FlyString default_role() const override { return DOM::ARIARoleNames::generic; } + private: HTMLDataElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h index 96b879420d..4de4419fb9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,8 @@ class HTMLDataListElement final : public HTMLElement { public: virtual ~HTMLDataListElement() override; + virtual FlyString default_role() const override { return DOM::ARIARoleNames::listbox; } + private: HTMLDataListElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h index 0ddf66f4c5..26eedd4219 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLDetailsElement final : public HTMLElement { public: virtual ~HTMLDetailsElement() override; + // https://www.w3.org/TR/html-aria/#el-details + virtual FlyString default_role() const override { return DOM::ARIARoleNames::group; }; + private: HTMLDetailsElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h index 2dbcda8e99..b81e6c1d3c 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLDialogElement final : public HTMLElement { public: virtual ~HTMLDialogElement() override; + // https://www.w3.org/TR/html-aria/#el-dialog + virtual FlyString default_role() const override { return DOM::ARIARoleNames::dialog; } + private: HTMLDialogElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h index 9cc973a00c..0dda8e975f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLDivElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLDivElement final : public HTMLElement { public: virtual ~HTMLDivElement() override; + // https://www.w3.org/TR/html-aria/#el-div + virtual FlyString default_role() const override { return DOM::ARIARoleNames::generic; } + private: HTMLDivElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp index e250d35744..27c5447f87 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -6,6 +6,7 @@ #include <AK/StringBuilder.h> #include <LibJS/Interpreter.h> +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/IDLEventListener.h> #include <LibWeb/DOM/ShadowRoot.h> @@ -327,4 +328,88 @@ void HTMLElement::blur() // User agents may selectively or uniformly ignore calls to this method for usability reasons. } +FlyString HTMLElement::default_role() const +{ + // https://www.w3.org/TR/html-aria/#el-article + if (local_name() == TagNames::article) + return DOM::ARIARoleNames::article; + // https://www.w3.org/TR/html-aria/#el-aside + if (local_name() == TagNames::aside) + return DOM::ARIARoleNames::complementary; + // https://www.w3.org/TR/html-aria/#el-b + if (local_name() == TagNames::b) + return DOM::ARIARoleNames::generic; + // https://www.w3.org/TR/html-aria/#el-bdi + if (local_name() == TagNames::bdi) + return DOM::ARIARoleNames::generic; + // https://www.w3.org/TR/html-aria/#el-bdo + if (local_name() == TagNames::bdo) + return DOM::ARIARoleNames::generic; + // https://www.w3.org/TR/html-aria/#el-code + if (local_name() == TagNames::code) + return DOM::ARIARoleNames::code; + // https://www.w3.org/TR/html-aria/#el-dfn + if (local_name() == TagNames::dfn) + return DOM::ARIARoleNames::term; + // https://www.w3.org/TR/html-aria/#el-em + if (local_name() == TagNames::em) + return DOM::ARIARoleNames::emphasis; + // https://www.w3.org/TR/html-aria/#el-figure + if (local_name() == TagNames::figure) + return DOM::ARIARoleNames::figure; + // https://www.w3.org/TR/html-aria/#el-footer + if (local_name() == TagNames::footer) { + // TODO: If not a descendant of an article, aside, main, nav or section element, or an element with role=article, complementary, main, navigation or region then role=contentinfo + // Otherwise, role=generic + return DOM::ARIARoleNames::generic; + } + // https://www.w3.org/TR/html-aria/#el-header + if (local_name() == TagNames::header) { + // TODO: If not a descendant of an article, aside, main, nav or section element, or an element with role=article, complementary, main, navigation or region then role=banner + // Otherwise, role=generic + return DOM::ARIARoleNames::generic; + } + // https://www.w3.org/TR/html-aria/#el-hgroup + if (local_name() == TagNames::hgroup) + return DOM::ARIARoleNames::generic; + // https://www.w3.org/TR/html-aria/#el-i + if (local_name() == TagNames::i) + return DOM::ARIARoleNames::generic; + // https://www.w3.org/TR/html-aria/#el-main + if (local_name() == TagNames::main) + return DOM::ARIARoleNames::main; + // https://www.w3.org/TR/html-aria/#el-nav + if (local_name() == TagNames::nav) + return DOM::ARIARoleNames::navigation; + // https://www.w3.org/TR/html-aria/#el-samp + if (local_name() == TagNames::samp) + return DOM::ARIARoleNames::generic; + // https://www.w3.org/TR/html-aria/#el-section + if (local_name() == TagNames::section) { + // TODO: role=region if the section element has an accessible name + // Otherwise, no corresponding role + return DOM::ARIARoleNames::region; + } + // https://www.w3.org/TR/html-aria/#el-small + if (local_name() == TagNames::small) + return DOM::ARIARoleNames::generic; + // https://www.w3.org/TR/html-aria/#el-strong + if (local_name() == TagNames::strong) + return DOM::ARIARoleNames::strong; + // https://www.w3.org/TR/html-aria/#el-sub + if (local_name() == TagNames::sub) + return DOM::ARIARoleNames::subscript; + // https://www.w3.org/TR/html-aria/#el-summary + if (local_name() == TagNames::summary) + return DOM::ARIARoleNames::button; + // https://www.w3.org/TR/html-aria/#el-sup + if (local_name() == TagNames::sup) + return DOM::ARIARoleNames::superscript; + // https://www.w3.org/TR/html-aria/#el-u + if (local_name() == TagNames::u) + return DOM::ARIARoleNames::generic; + + return {}; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.h b/Userland/Libraries/LibWeb/HTML/HTMLElement.h index 30634c241d..9e1c1a402e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.h @@ -59,6 +59,8 @@ public: // https://html.spec.whatwg.org/multipage/forms.html#category-label virtual bool is_labelable() const { return false; } + virtual FlyString default_role() const override; + protected: HTMLElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h index f94931dd8c..532b62da3e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/FormAssociatedElement.h> #include <LibWeb/HTML/HTMLElement.h> @@ -35,6 +36,8 @@ public: // https://html.spec.whatwg.org/multipage/forms.html#category-autocapitalize virtual bool is_auto_capitalize_inheriting() const override { return true; } + virtual FlyString default_role() const override { return DOM::ARIARoleNames::group; } + private: HTMLFieldSetElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h index 3c10fc05c6..e380d68d1d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLFormElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> #include <LibWeb/HTML/HTMLInputElement.h> @@ -36,6 +37,9 @@ public: JS::NonnullGCPtr<DOM::HTMLCollection> elements() const; unsigned length() const; + // https://www.w3.org/TR/html-aria/#el-form + virtual FlyString default_role() const override { return DOM::ARIARoleNames::form; } + private: HTMLFormElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h index a9516b4231..4b13e4882e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHRElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLHRElement final : public HTMLElement { public: virtual ~HTMLHRElement() override; + // https://www.w3.org/TR/html-aria/#el-hr + virtual FlyString default_role() const override { return DOM::ARIARoleNames::separator; } + private: HTMLHRElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h index 9dcd4aa61e..6093993ce3 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -18,6 +19,14 @@ public: virtual void apply_presentational_hints(CSS::StyleProperties&) const override; + // https://www.w3.org/TR/html-aria/#el-h1-h6 + virtual FlyString default_role() const override { return DOM::ARIARoleNames::heading; } + virtual DeprecatedString aria_level() const override + { + // TODO: aria-level = the number in the element's tag name + return get_attribute("aria-level"); + } + private: HTMLHeadingElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h b/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h index 433a50b1c0..272d6af62a 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -18,6 +19,9 @@ public: bool should_use_body_background_properties() const; + // https://www.w3.org/TR/html-aria/#el-html + virtual FlyString default_role() const override { return DOM::ARIARoleNames::document; } + private: HTMLHtmlElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp index a74bc35d4f..55cb5e4737 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -7,6 +7,7 @@ #include <LibGfx/Bitmap.h> #include <LibWeb/CSS/Parser/Parser.h> #include <LibWeb/CSS/StyleComputer.h> +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Event.h> #include <LibWeb/HTML/EventNames.h> @@ -197,4 +198,14 @@ bool HTMLImageElement::complete() const return false; } +FlyString HTMLImageElement::default_role() const +{ + // https://www.w3.org/TR/html-aria/#el-img + // https://www.w3.org/TR/html-aria/#el-img-no-alt + if (alt().is_null() || !alt().is_empty()) + return DOM::ARIARoleNames::img; + // https://www.w3.org/TR/html-aria/#el-img-empty-alt + return DOM::ARIARoleNames::presentation; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h index 8a8281e89d..ee72cfa1ab 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.h @@ -43,6 +43,8 @@ public: // https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-complete bool complete() const; + virtual FlyString default_role() const override; + private: HTMLImageElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 74946382bb..ae20f490aa 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -866,4 +866,66 @@ WebIDL::ExceptionOr<void> HTMLInputElement::set_selection_range(u32 start, u32 e return {}; } +FlyString HTMLInputElement::default_role() const +{ + // https://www.w3.org/TR/html-aria/#el-input-button + if (type_state() == TypeAttributeState::Button) + return DOM::ARIARoleNames::button; + // https://www.w3.org/TR/html-aria/#el-input-checkbox + if (type_state() == TypeAttributeState::Checkbox) + return DOM::ARIARoleNames::checkbox; + // https://www.w3.org/TR/html-aria/#el-input-email + if (type_state() == TypeAttributeState::Email && attribute("list").is_null()) + return DOM::ARIARoleNames::textbox; + // https://www.w3.org/TR/html-aria/#el-input-image + if (type_state() == TypeAttributeState::ImageButton) + return DOM::ARIARoleNames::button; + // https://www.w3.org/TR/html-aria/#el-input-number + if (type_state() == TypeAttributeState::Number) + return DOM::ARIARoleNames::spinbutton; + // https://www.w3.org/TR/html-aria/#el-input-radio + if (type_state() == TypeAttributeState::RadioButton) + return DOM::ARIARoleNames::radio; + // https://www.w3.org/TR/html-aria/#el-input-range + if (type_state() == TypeAttributeState::Range) + return DOM::ARIARoleNames::slider; + // https://www.w3.org/TR/html-aria/#el-input-reset + if (type_state() == TypeAttributeState::ResetButton) + return DOM::ARIARoleNames::button; + // https://www.w3.org/TR/html-aria/#el-input-text-list + if ((type_state() == TypeAttributeState::Text + || type_state() == TypeAttributeState::Search + || type_state() == TypeAttributeState::Telephone + || type_state() == TypeAttributeState::URL + || type_state() == TypeAttributeState::Email) + && !attribute("list").is_null()) + return DOM::ARIARoleNames::combobox; + // https://www.w3.org/TR/html-aria/#el-input-search + if (type_state() == TypeAttributeState::Search && attribute("list").is_null()) + return DOM::ARIARoleNames::textbox; + // https://www.w3.org/TR/html-aria/#el-input-submit + if (type_state() == TypeAttributeState::SubmitButton) + return DOM::ARIARoleNames::button; + // https://www.w3.org/TR/html-aria/#el-input-tel + if (type_state() == TypeAttributeState::Telephone) + return DOM::ARIARoleNames::textbox; + // https://www.w3.org/TR/html-aria/#el-input-text + if (type_state() == TypeAttributeState::Text && attribute("list").is_null()) + return DOM::ARIARoleNames::textbox; + // https://www.w3.org/TR/html-aria/#el-input-url + if (type_state() == TypeAttributeState::URL && attribute("list").is_null()) + return DOM::ARIARoleNames::textbox; + + // https://www.w3.org/TR/html-aria/#el-input-color + // https://www.w3.org/TR/html-aria/#el-input-date + // https://www.w3.org/TR/html-aria/#el-input-datetime-local + // https://www.w3.org/TR/html-aria/#el-input-file + // https://www.w3.org/TR/html-aria/#el-input-hidden + // https://www.w3.org/TR/html-aria/#el-input-month + // https://www.w3.org/TR/html-aria/#el-input-password + // https://www.w3.org/TR/html-aria/#el-input-time + // https://www.w3.org/TR/html-aria/#el-input-week + return {}; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h index bda31d044e..8bb9b4ee2f 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLInputElement.h @@ -120,6 +120,8 @@ public: // https://html.spec.whatwg.org/multipage/forms.html#category-label virtual bool is_labelable() const override { return type_state() != TypeAttributeState::Hidden; } + virtual FlyString default_role() const override; + private: HTMLInputElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h b/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h index efb14477eb..6b5ed2b23e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLLIElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLLIElement final : public HTMLElement { public: virtual ~HTMLLIElement() override; + // https://www.w3.org/TR/html-aria/#el-li + virtual FlyString default_role() const override { return DOM::ARIARoleNames::listitem; }; + private: HTMLLIElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h index 7ac8e896d9..fffd674965 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLMenuElement final : public HTMLElement { public: virtual ~HTMLMenuElement() override; + // https://www.w3.org/TR/html-aria/#el-menu + virtual FlyString default_role() const override { return DOM::ARIARoleNames::list; } + private: HTMLMenuElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h b/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h index 3a13f1a43b..86a6880eff 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h @@ -7,6 +7,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -21,6 +22,9 @@ public: // https://html.spec.whatwg.org/multipage/forms.html#category-label virtual bool is_labelable() const override { return true; } + // https://www.w3.org/TR/html-aria/#el-meter + virtual FlyString default_role() const override { return DOM::ARIARoleNames::meter; } + private: HTMLMeterElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLModElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLModElement.cpp index 50141f521b..60ce086bc1 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLModElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLModElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <AK/Assertions.h> #include <LibWeb/Bindings/Intrinsics.h> #include <LibWeb/HTML/HTMLModElement.h> @@ -17,4 +18,15 @@ HTMLModElement::HTMLModElement(DOM::Document& document, DOM::QualifiedName quali HTMLModElement::~HTMLModElement() = default; +FlyString HTMLModElement::default_role() const +{ + // https://www.w3.org/TR/html-aria/#el-del + if (local_name() == TagNames::del) + return DOM::ARIARoleNames::deletion; + // https://www.w3.org/TR/html-aria/#el-ins + if (local_name() == TagNames::ins) + return DOM::ARIARoleNames::insertion; + VERIFY_NOT_REACHED(); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLModElement.h b/Userland/Libraries/LibWeb/HTML/HTMLModElement.h index efcae94c1c..2dbc748a8e 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLModElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLModElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,8 @@ class HTMLModElement final : public HTMLElement { public: virtual ~HTMLModElement() override; + virtual FlyString default_role() const override; + private: HTMLModElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h index 7e3c197a05..9ff8034f24 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOListElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLOListElement final : public HTMLElement { public: virtual ~HTMLOListElement() override; + // https://www.w3.org/TR/html-aria/#el-ol + virtual FlyString default_role() const override { return DOM::ARIARoleNames::list; } + private: HTMLOListElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h index 3dab2641f5..708c09ad1b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLOptGroupElement final : public HTMLElement { public: virtual ~HTMLOptGroupElement() override; + // https://www.w3.org/TR/html-aria/#el-optgroup + virtual FlyString default_role() const override { return DOM::ARIARoleNames::group; } + private: HTMLOptGroupElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp index 1009a9032b..4396f9d9cf 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp @@ -7,6 +7,7 @@ #include <AK/StringBuilder.h> #include <LibWeb/Bindings/Intrinsics.h> +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/DOM/Node.h> #include <LibWeb/DOM/Text.h> #include <LibWeb/HTML/HTMLOptGroupElement.h> @@ -140,4 +141,11 @@ bool HTMLOptionElement::disabled() const || (parent() && is<HTMLOptGroupElement>(parent()) && static_cast<HTMLOptGroupElement const&>(*parent()).has_attribute(AttributeNames::disabled)); } +FlyString HTMLOptionElement::default_role() const +{ + // https://www.w3.org/TR/html-aria/#el-option + // TODO: Only an option element that is in a list of options or that represents a suggestion in a datalist should return option + return DOM::ARIARoleNames::option; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.h index f48365a8ef..2083fc30bc 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOptionElement.h @@ -30,6 +30,8 @@ public: bool disabled() const; + virtual FlyString default_role() const override; + private: friend class Bindings::OptionConstructor; friend class HTMLSelectElement; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h index 70c075a06f..0012795625 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h @@ -7,6 +7,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/FormAssociatedElement.h> #include <LibWeb/HTML/HTMLElement.h> @@ -43,6 +44,9 @@ public: virtual void reset_algorithm() override; + // https://www.w3.org/TR/html-aria/#el-output + virtual FlyString default_role() const override { return DOM::ARIARoleNames::status; } + private: HTMLOutputElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h b/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h index b18f7d19fe..6c2cb0cae7 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -18,6 +19,9 @@ public: virtual void apply_presentational_hints(CSS::StyleProperties&) const override; + // https://www.w3.org/TR/html-aria/#el-p + virtual FlyString default_role() const override { return DOM::ARIARoleNames::paragraph; } + private: HTMLParagraphElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h b/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h index 4aa296e069..bf7f793df3 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLPreElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLPreElement final : public HTMLElement { public: virtual ~HTMLPreElement() override; + // https://www.w3.org/TR/html-aria/#el-pre + virtual FlyString default_role() const override { return DOM::ARIARoleNames::generic; } + private: HTMLPreElement(DOM::Document&, DOM::QualifiedName); virtual void apply_presentational_hints(CSS::StyleProperties&) const override; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h index 414769514b..9e51af0d50 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -32,6 +33,9 @@ public: bool using_system_appearance() const; + // https://www.w3.org/TR/html-aria/#el-progress + virtual FlyString default_role() const override { return DOM::ARIARoleNames::progressbar; } + private: HTMLProgressElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.cpp index 71f1b5743e..6bca0b337b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.cpp @@ -4,7 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <AK/Assertions.h> #include <LibWeb/Bindings/Intrinsics.h> +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLQuoteElement.h> namespace Web::HTML { @@ -17,4 +19,15 @@ HTMLQuoteElement::HTMLQuoteElement(DOM::Document& document, DOM::QualifiedName q HTMLQuoteElement::~HTMLQuoteElement() = default; +FlyString HTMLQuoteElement::default_role() const +{ + // https://www.w3.org/TR/html-aria/#el-blockquote + if (local_name() == TagNames::blockquote) + return DOM::ARIARoleNames::blockquote; + // https://www.w3.org/TR/html-aria/#el-q + if (local_name() == TagNames::q) + return DOM::ARIARoleNames::generic; + VERIFY_NOT_REACHED(); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h index 6e511a8d65..da36f18ce6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h @@ -16,6 +16,8 @@ class HTMLQuoteElement final : public HTMLElement { public: virtual ~HTMLQuoteElement() override; + virtual FlyString default_role() const override; + private: HTMLQuoteElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp index 60691c8907..29d23803a6 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp @@ -156,4 +156,18 @@ DeprecatedString const& HTMLSelectElement::type() const return select_multiple; } +FlyString HTMLSelectElement::default_role() const +{ + // https://www.w3.org/TR/html-aria/#el-select-multiple-or-size-greater-1 + if (has_attribute("multiple")) + return DOM::ARIARoleNames::listbox; + if (has_attribute("size")) { + auto size_attribute = attribute("size").to_int(); + if (size_attribute.has_value() && size_attribute.value() > 1) + return DOM::ARIARoleNames::listbox; + } + // https://www.w3.org/TR/html-aria/#el-select + return DOM::ARIARoleNames::combobox; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h index 64288d1c24..d08e9bd69d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h @@ -60,6 +60,8 @@ public: DeprecatedString const& type() const; + virtual FlyString default_role() const override; + private: HTMLSelectElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h index c36aa654ad..3a3faf3df2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLSpanElement final : public HTMLElement { public: virtual ~HTMLSpanElement() override; + // https://www.w3.org/TR/html-aria/#el-span + virtual FlyString default_role() const override { return DOM::ARIARoleNames::generic; } + private: HTMLSpanElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h index ec68ce04b7..3393faadf3 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -18,6 +19,9 @@ public: virtual void apply_presentational_hints(CSS::StyleProperties&) const override; + // https://www.w3.org/TR/html-aria/#el-caption + virtual FlyString default_role() const override { return DOM::ARIARoleNames::caption; } + private: HTMLTableCaptionElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp index 330712a8db..0b4c2d3df2 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp @@ -69,4 +69,19 @@ void HTMLTableCellElement::set_row_span(unsigned int value) MUST(set_attribute(HTML::AttributeNames::rowspan, DeprecatedString::number(value))); } +FlyString HTMLTableCellElement::default_role() const +{ + // TODO: For td: + // role=cell if the ancestor table element is exposed as a role=table + // role=gridcell if the ancestor table element is exposed as a role=grid or treegrid + // No corresponding role if the ancestor table element is not exposed as a role=table, grid or treegrid + // For th: + // role=columnheader, rowheader or cell if the ancestor table element is exposed as a role=table + // role=columnheader, rowheader or gridcell if the ancestor table element is exposed as a role=grid or treegrid + // No corresponding role if the ancestor table element is not exposed as a role=table, grid or treegrid + // https://www.w3.org/TR/html-aria/#el-td + // https://www.w3.org/TR/html-aria/#el-th + return {}; +} + } diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h index 8b52ad59d5..53e281073d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h @@ -22,6 +22,8 @@ public: void set_col_span(unsigned); void set_row_span(unsigned); + virtual FlyString default_role() const override; + private: HTMLTableCellElement(DOM::Document&, DOM::QualifiedName); virtual void apply_presentational_hints(CSS::StyleProperties&) const override; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h index d9fa4e9e9f..cf36ec6934 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableElement.h @@ -42,6 +42,9 @@ public: WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLTableRowElement>> insert_row(long index); WebIDL::ExceptionOr<void> delete_row(long index); + // https://www.w3.org/TR/html-aria/#el-table + virtual FlyString default_role() const override { return DOM::ARIARoleNames::table; } + private: HTMLTableElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.h index 1ee1b10f1d..ee3fc521d9 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -23,6 +24,9 @@ public: WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLTableCellElement>> insert_cell(i32 index); WebIDL::ExceptionOr<void> delete_cell(i32 index); + // https://www.w3.org/TR/html-aria/#el-tr + virtual FlyString default_role() const override { return DOM::ARIARoleNames::row; } + private: HTMLTableRowElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.h index 76b9bbed1e..083654b99d 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.h @@ -7,6 +7,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -21,6 +22,11 @@ public: WebIDL::ExceptionOr<JS::NonnullGCPtr<HTMLTableRowElement>> insert_row(long index); WebIDL::ExceptionOr<void> delete_row(long index); + // https://www.w3.org/TR/html-aria/#el-tbody + // https://www.w3.org/TR/html-aria/#el-tfoot + // https://www.w3.org/TR/html-aria/#el-thead + virtual FlyString default_role() const override { return DOM::ARIARoleNames::rowgroup; } + private: HTMLTableSectionElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h index 5d29fcd8fc..939ec8fe85 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h @@ -7,6 +7,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/FormAssociatedElement.h> #include <LibWeb/HTML/HTMLElement.h> @@ -50,6 +51,9 @@ public: virtual void reset_algorithm() override; + // https://www.w3.org/TR/html-aria/#el-textarea + virtual FlyString default_role() const override { return DOM::ARIARoleNames::textbox; } + private: HTMLTextAreaElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h b/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h index 9085662d44..3272d31309 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLTimeElement final : public HTMLElement { public: virtual ~HTMLTimeElement() override; + // https://www.w3.org/TR/html-aria/#el-time + virtual FlyString default_role() const override { return DOM::ARIARoleNames::time; } + private: HTMLTimeElement(DOM::Document&, DOM::QualifiedName); }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h index e421831c90..5af03e8797 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLUListElement.h @@ -6,6 +6,7 @@ #pragma once +#include <LibWeb/DOM/ARIARoleNames.h> #include <LibWeb/HTML/HTMLElement.h> namespace Web::HTML { @@ -16,6 +17,9 @@ class HTMLUListElement final : public HTMLElement { public: virtual ~HTMLUListElement() override; + // https://www.w3.org/TR/html-aria/#el-ul + virtual FlyString default_role() const override { return DOM::ARIARoleNames::list; } + private: HTMLUListElement(DOM::Document&, DOM::QualifiedName); }; |