/* * Copyright (c) 2023, Jonah Shafran * Copyright (c) 2023, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ #include #include namespace Web::ARIA { AriaData::AriaData(Web::ARIA::ARIAMixin const& source) { m_aria_active_descendant = source.aria_active_descendant(); m_aria_atomic = AriaData::parse_optional_true_false(source.aria_atomic()); m_aria_auto_complete = AriaData::parse_aria_autocomplete(source.aria_auto_complete()); m_aria_busy = AriaData::parse_true_false(source.aria_busy()); m_aria_checked = AriaData::parse_tristate(source.aria_checked()); m_aria_col_count = AriaData::parse_integer(source.aria_col_count()); m_aria_col_index = AriaData::parse_integer(source.aria_col_index()); m_aria_col_span = AriaData::parse_integer(source.aria_col_span()); m_aria_controls = source.parse_id_reference_list(source.aria_controls()); m_aria_current = AriaData::parse_aria_current(source.aria_current()); m_aria_described_by = source.parse_id_reference_list(source.aria_described_by()); m_aria_details = source.parse_id_reference(source.aria_details()); m_aria_disabled = AriaData::parse_true_false(source.aria_disabled()); m_aria_drop_effect = AriaData::parse_aria_drop_effect(source.aria_drop_effect()); m_aria_error_message = source.parse_id_reference(source.aria_error_message()); m_aria_expanded = AriaData::parse_true_false_undefined(source.aria_expanded()); m_aria_flow_to = source.parse_id_reference_list(source.aria_flow_to()); m_aria_grabbed = AriaData::parse_true_false_undefined(source.aria_grabbed()); m_aria_has_popup = AriaData::parse_aria_has_popup(source.aria_has_popup()); m_aria_hidden = AriaData::parse_true_false_undefined(source.aria_hidden()); m_aria_invalid = AriaData::parse_aria_invalid(source.aria_invalid()); m_aria_key_shortcuts = source.aria_key_shortcuts().value_or(String {}); m_aria_label = source.aria_label().value_or(String {}); m_aria_labelled_by = source.parse_id_reference_list(source.aria_labelled_by()); m_aria_level = AriaData::parse_integer(source.aria_level()); m_aria_live = AriaData::parse_aria_live(source.aria_live()); m_aria_modal = AriaData::parse_true_false(source.aria_modal()); m_aria_multi_line = AriaData::parse_true_false(source.aria_multi_line()); m_aria_multi_selectable = AriaData::parse_true_false(source.aria_multi_selectable()); m_aria_orientation = AriaData::parse_aria_orientation(source.aria_orientation()); m_aria_owns = source.parse_id_reference_list(source.aria_owns()); m_aria_placeholder = source.aria_placeholder().value_or(String {}); m_aria_pos_in_set = AriaData::parse_integer(source.aria_pos_in_set()); m_aria_pressed = AriaData::parse_tristate(source.aria_pressed()); m_aria_read_only = AriaData::parse_true_false(source.aria_read_only()); m_aria_relevant = AriaData::parse_aria_relevant(source.aria_relevant()); m_aria_required = AriaData::parse_true_false(source.aria_required()); m_aria_role_description = source.aria_role_description().value_or(String {}); m_aria_row_count = AriaData::parse_integer(source.aria_row_count()); m_aria_row_index = AriaData::parse_integer(source.aria_row_index()); m_aria_row_span = AriaData::parse_integer(source.aria_row_span()); m_aria_selected = AriaData::parse_true_false_undefined(source.aria_selected()); m_aria_set_size = AriaData::parse_integer(source.aria_set_size()); m_aria_sort = AriaData::parse_aria_sort(source.aria_sort()); m_aria_value_max = AriaData::parse_number(source.aria_value_max()); m_aria_value_min = AriaData::parse_number(source.aria_value_min()); m_aria_value_now = AriaData::parse_number(source.aria_value_now()); m_aria_value_text = source.aria_value_text().value_or(String {}); } bool AriaData::parse_true_false(Optional const& value) { if (value == "true"sv) return true; if (value == "false"sv) return false; return false; } Tristate AriaData::parse_tristate(Optional const& value) { if (value == "true"sv) return Tristate::True; if (value == "false"sv) return Tristate::False; if (value == "mixed"sv) return Tristate::Mixed; if (value == "undefined"sv) return Tristate::Undefined; return Tristate::Undefined; } Optional AriaData::parse_true_false_undefined(Optional const& value) { if (value == "true"sv) return true; if (value == "false"sv) return false; if (value == "undefined"sv) return {}; return {}; } Optional AriaData::parse_integer(Optional const& value) { if (!value.has_value()) return {}; return value->bytes_as_string_view().to_number(); } Optional AriaData::parse_number(Optional const& value) { if (!value.has_value()) return {}; return value->to_number(TrimWhitespace::Yes); } Optional AriaData::aria_active_descendant_or_default() const { return m_aria_active_descendant; } bool AriaData::aria_atomic_or_default(bool default_value) const { auto value = m_aria_atomic; if (!value.has_value()) return default_value; return value.value(); } AriaAutocomplete AriaData::aria_auto_complete_or_default() const { return m_aria_auto_complete; } bool AriaData::aria_busy_or_default() const { return m_aria_busy; } Tristate AriaData::aria_checked_or_default() const { return m_aria_checked; } Optional AriaData::aria_col_count_or_default() const { return m_aria_col_count; } Optional AriaData::aria_col_index_or_default() const { return m_aria_col_index; } Optional AriaData::aria_col_span_or_default() const { return m_aria_col_span; } Vector AriaData::aria_controls_or_default() const { return m_aria_controls; } AriaCurrent AriaData::aria_current_or_default() const { return m_aria_current; } Vector AriaData::aria_described_by_or_default() const { return m_aria_described_by; } Optional AriaData::aria_details_or_default() const { return m_aria_details; } bool AriaData::aria_disabled_or_default() const { return m_aria_disabled; } Vector AriaData::aria_drop_effect_or_default() const { return m_aria_drop_effect; } Optional AriaData::aria_error_message_or_default() const { return m_aria_error_message; } Optional AriaData::aria_expanded_or_default() const { return m_aria_expanded; } Vector AriaData::aria_flow_to_or_default() const { return m_aria_flow_to; } Optional AriaData::aria_grabbed_or_default() const { return m_aria_grabbed; } AriaHasPopup AriaData::aria_has_popup_or_default() const { return m_aria_has_popup; } Optional AriaData::aria_hidden_or_default() const { return m_aria_hidden; } AriaInvalid AriaData::aria_invalid_or_default() const { return m_aria_invalid; } String AriaData::aria_key_shortcuts_or_default() const { return m_aria_key_shortcuts; } String AriaData::aria_label_or_default() const { return m_aria_label; } Vector AriaData::aria_labelled_by_or_default() const { return m_aria_labelled_by; } Optional AriaData::aria_level_or_default() const { return m_aria_level; } AriaLive AriaData::aria_live_or_default(AriaLive default_value) const { auto value = m_aria_live; if (!value.has_value()) return default_value; return value.value(); } bool AriaData::aria_modal_or_default() const { return m_aria_modal; } bool AriaData::aria_multi_line_or_default() const { return m_aria_multi_line; } bool AriaData::aria_multi_selectable_or_default() const { return m_aria_multi_selectable; } AriaOrientation AriaData::aria_orientation_or_default(AriaOrientation default_value) const { auto value = m_aria_orientation; if (!value.has_value()) return default_value; return value.value(); } Vector AriaData::aria_owns_or_default() const { return m_aria_owns; } String AriaData::aria_placeholder_or_default() const { return m_aria_placeholder; } Optional AriaData::aria_pos_in_set_or_default() const { return m_aria_pos_in_set; } Tristate AriaData::aria_pressed_or_default() const { return m_aria_pressed; } bool AriaData::aria_read_only_or_default() const { return m_aria_read_only; } Vector AriaData::aria_relevant_or_default() const { return m_aria_relevant; } bool AriaData::aria_required_or_default() const { return m_aria_required; } String AriaData::aria_role_description_or_default() const { return m_aria_role_description; } Optional AriaData::aria_row_count_or_default() const { return m_aria_row_count; } Optional AriaData::aria_row_index_or_default() const { return m_aria_row_index; } Optional AriaData::aria_row_span_or_default() const { return m_aria_row_span; } Optional AriaData::aria_selected_or_default() const { return m_aria_selected; } Optional AriaData::aria_set_size_or_default() const { return m_aria_set_size; } AriaSort AriaData::aria_sort_or_default() const { return m_aria_sort; } Optional AriaData::aria_value_max_or_default(Optional default_value) const { auto value = m_aria_value_max; if (!value.has_value()) return default_value; return value; } Optional AriaData::aria_value_min_or_default(Optional default_value) const { auto value = m_aria_value_min; if (!value.has_value()) return default_value; return value; } Optional AriaData::aria_value_now_or_default() const { return m_aria_value_now; } String AriaData::aria_value_text_or_default() const { return m_aria_value_text; } AriaAutocomplete AriaData::parse_aria_autocomplete(Optional const& value) { if (value == "inline"sv) return AriaAutocomplete::Inline; if (value == "list"sv) return AriaAutocomplete::List; if (value == "both"sv) return AriaAutocomplete::Both; if (value == "none"sv) return AriaAutocomplete::None; return AriaAutocomplete::None; } AriaCurrent AriaData::parse_aria_current(Optional const& value) { if (value == "page"sv) return AriaCurrent::Page; if (value == "step"sv) return AriaCurrent::Step; if (value == "location"sv) return AriaCurrent::Location; if (value == "date"sv) return AriaCurrent::Date; if (value == "time"sv) return AriaCurrent::Time; if (value == "true"sv) return AriaCurrent::True; if (value == "false"sv) return AriaCurrent::False; return AriaCurrent::False; } Vector AriaData::parse_aria_drop_effect(Optional const& value) { if (!value.has_value()) return {}; Vector result; for (auto token : value->bytes_as_string_view().split_view_if(Infra::is_ascii_whitespace)) { if (token == "copy"sv) result.append(AriaDropEffect::Copy); else if (token == "execute"sv) result.append(AriaDropEffect::Execute); else if (token == "link"sv) result.append(AriaDropEffect::Link); else if (token == "move"sv) result.append(AriaDropEffect::Move); else if (token == "popup"sv) result.append(AriaDropEffect::Popup); } // None combined with any other token value is ignored if (result.is_empty()) result.append(AriaDropEffect::None); return result; } AriaHasPopup AriaData::parse_aria_has_popup(Optional const& value) { if (value == "false"sv) return AriaHasPopup::False; if (value == "true"sv) return AriaHasPopup::True; if (value == "menu"sv) return AriaHasPopup::Menu; if (value == "listbox"sv) return AriaHasPopup::Listbox; if (value == "tree"sv) return AriaHasPopup::Tree; if (value == "grid"sv) return AriaHasPopup::Grid; if (value == "dialog"sv) return AriaHasPopup::Dialog; return AriaHasPopup::False; } AriaInvalid AriaData::parse_aria_invalid(Optional const& value) { if (value == "grammar"sv) return AriaInvalid::Grammar; if (value == "false"sv) return AriaInvalid::False; if (value == "spelling"sv) return AriaInvalid::Spelling; if (value == "true"sv) return AriaInvalid::True; return AriaInvalid::False; } Optional AriaData::parse_aria_live(Optional const& value) { if (value == "assertive"sv) return AriaLive::Assertive; if (value == "off"sv) return AriaLive::Off; if (value == "polite"sv) return AriaLive::Polite; return {}; } Optional AriaData::parse_aria_orientation(Optional const& value) { if (value == "horizontal"sv) return AriaOrientation::Horizontal; if (value == "undefined"sv) return AriaOrientation::Undefined; if (value == "vertical"sv) return AriaOrientation::Vertical; return {}; } Vector AriaData::parse_aria_relevant(Optional const& value) { if (!value.has_value()) return {}; Vector result; auto tokens = value->bytes_as_string_view().split_view_if(Infra::is_ascii_whitespace); for (size_t i = 0; i < tokens.size(); i++) { if (tokens[i] == "additions"sv) { if (i + 1 < tokens.size()) { if (tokens[i + 1] == "text"sv) { result.append(AriaRelevant::AdditionsText); ++i; continue; } if (tokens[i + 1] == "removals"sv && i + 2 < tokens.size() && tokens[i + 2] == "text"sv) { result.append(AriaRelevant::All); i += 2; continue; } } result.append(AriaRelevant::Additions); } else if (tokens[i] == "all"sv) result.append(AriaRelevant::All); else if (tokens[i] == "removals"sv) result.append(AriaRelevant::Removals); else if (tokens[i] == "text"sv) result.append(AriaRelevant::Text); } if (result.is_empty()) result.append(AriaRelevant::AdditionsText); return result; } AriaSort AriaData::parse_aria_sort(Optional const& value) { if (value == "ascending"sv) return AriaSort::Ascending; if (value == "descending"sv) return AriaSort::Descending; if (value == "none"sv) return AriaSort::None; if (value == "other"sv) return AriaSort::Other; return AriaSort::None; } Optional AriaData::parse_optional_true_false(Optional const& value) { if (value == "true"sv) return true; if (value == "false"sv) return false; return {}; } }