summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibWeb/CMakeLists.txt3
-rw-r--r--Userland/Libraries/LibWeb/DOM/ARIAMixin.cpp35
-rw-r--r--Userland/Libraries/LibWeb/DOM/ARIAMixin.h143
-rw-r--r--Userland/Libraries/LibWeb/DOM/ARIAMixin.idl53
-rw-r--r--Userland/Libraries/LibWeb/DOM/ARIARoleNames.cpp167
-rw-r--r--Userland/Libraries/LibWeb/DOM/ARIARoleNames.h122
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.h70
-rw-r--r--Userland/Libraries/LibWeb/DOM/Element.idl3
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp10
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLAreaElement.cpp10
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLAreaElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLBodyElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLButtonElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLDataElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLDataListElement.h3
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLDetailsElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLDialogElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLDivElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLElement.cpp85
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLFieldSetElement.h3
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLFormElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLHRElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLHeadingElement.h9
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLHtmlElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp11
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLImageElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLInputElement.cpp62
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLInputElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLLIElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLMenuElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLMeterElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLModElement.cpp12
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLModElement.h3
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOListElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOptGroupElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOptionElement.cpp8
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOptionElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLOutputElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLParagraphElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLPreElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLProgressElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.cpp13
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLQuoteElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLSelectElement.cpp14
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLSelectElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLSpanElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTableCaptionElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.cpp15
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTableCellElement.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTableElement.h3
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTableRowElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTableSectionElement.h6
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTextAreaElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLTimeElement.h4
-rw-r--r--Userland/Libraries/LibWeb/HTML/HTMLUListElement.h4
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);
};