diff --git a/Libraries/LibWeb/SVG/SVGElement.cpp b/Libraries/LibWeb/SVG/SVGElement.cpp index 538767205e0..583b9ad2709 100644 --- a/Libraries/LibWeb/SVG/SVGElement.cpp +++ b/Libraries/LibWeb/SVG/SVGElement.cpp @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include namespace Web::SVG { @@ -28,6 +30,38 @@ void SVGElement::initialize(JS::Realm& realm) WEB_SET_PROTOTYPE_FOR_INTERFACE(SVGElement); } +bool SVGElement::should_include_in_accessibility_tree() const +{ + bool has_title_or_desc = false; + auto role = role_from_role_attribute_value(); + for_each_child_of_type([&has_title_or_desc](auto& child) { + if ((is(child) || is(child)) && !child.text_content()->trim_ascii_whitespace().value().is_empty()) { + has_title_or_desc = true; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + // https://w3c.github.io/svg-aam/#include_elements + // TODO: Add support for the SVG tabindex attribute, and include a check for it here. + return has_title_or_desc + || (aria_label().has_value() && !aria_label().value().trim_ascii_whitespace().value().is_empty()) + || (aria_labelled_by().has_value() && !aria_labelled_by().value().trim_ascii_whitespace().value().is_empty()) + || (aria_described_by().has_value() && !aria_described_by().value().trim_ascii_whitespace().value().is_empty()) + || (role.has_value() && ARIA::is_abstract_role(role.value()) && role != ARIA::Role::none && role != ARIA::Role::presentation); +} + +Optional SVGElement::default_role() const +{ + // https://w3c.github.io/svg-aam/#mapping_role_table + if (local_name() == TagNames::a && (has_attribute(SVG::AttributeNames::href) || has_attribute(AttributeNames::xlink_href))) + return ARIA::Role::link; + if (local_name() == TagNames::g && should_include_in_accessibility_tree()) + return ARIA::Role::group; + if (local_name() == TagNames::image && should_include_in_accessibility_tree()) + return ARIA::Role::image; + return {}; +} + void SVGElement::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); diff --git a/Libraries/LibWeb/SVG/SVGElement.h b/Libraries/LibWeb/SVG/SVGElement.h index 357a041b4ff..2bf605a5256 100644 --- a/Libraries/LibWeb/SVG/SVGElement.h +++ b/Libraries/LibWeb/SVG/SVGElement.h @@ -25,6 +25,9 @@ public: GC::Ref class_name(); GC::Ptr owner_svg_element(); + bool should_include_in_accessibility_tree() const; + virtual Optional default_role() const override; + protected: SVGElement(DOM::Document&, DOM::QualifiedName); diff --git a/Tests/LibWeb/Text/expected/wpt-import/svg-aam/role/roles.txt b/Tests/LibWeb/Text/expected/wpt-import/svg-aam/role/roles.txt new file mode 100644 index 00000000000..2a7f0d7afea --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/svg-aam/role/roles.txt @@ -0,0 +1,9 @@ +Harness status: OK + +Found 4 tests + +4 Pass +Pass el-a[href] +Pass el-a[xlink:href] +Pass el-g +Pass el-image \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/svg-aam/role/roles.html b/Tests/LibWeb/Text/input/wpt-import/svg-aam/role/roles.html new file mode 100644 index 00000000000..b2f248f352a --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/svg-aam/role/roles.html @@ -0,0 +1,107 @@ + + + + SVG-AAM Role Verification Tests + + + + + + + + + + +

Tests the mappings defined in SVG-AAM: 6.2 Element Mapping.

+ +

Simple Elements With aria-label to Ensure Tree Inclusion

+ + + x + x + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file