mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibWeb: Fix accessible-name computation for pseudo-element content
This change fixes handling for substep ii of the “F. Name From Content” step at https://w3c.github.io/accname/#step2F in the “Accessible Name and Description Computation” spec — to correctly include any ::before and ::after pseudo-element content in the computation of accessible names. Otherwise, without this change, accessible names unexpectedly don’t include that pseudo-element content.
This commit is contained in:
parent
3ba7c53668
commit
b1587cc60f
Notes:
github-actions[bot]
2024-11-11 21:58:09 +00:00
Author: https://github.com/sideshowbarker Commit: https://github.com/LadybirdBrowser/ladybird/commit/b1587cc60f9 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2194 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/AtkinsSJ
3 changed files with 24 additions and 14 deletions
|
@ -330,7 +330,7 @@ struct ContentData {
|
|||
|
||||
// FIXME: Data is a list of identifiers, strings and image values.
|
||||
String data {};
|
||||
String alt_text {};
|
||||
Optional<String> alt_text {};
|
||||
};
|
||||
|
||||
struct CounterData {
|
||||
|
|
|
@ -2333,17 +2333,20 @@ ErrorOr<String> Node::name_or_description(NameOrDescription target, Document con
|
|||
if ((role.has_value() && ARIA::allows_name_from_content(role.value())) || is_descendant == IsDescendant::Yes) {
|
||||
// i. Set the accumulated text to the empty string.
|
||||
total_accumulated_text.clear();
|
||||
// ii. Check for CSS generated textual content associated with the current node and include it in the accumulated text. The CSS :before and :after pseudo elements [CSS2] can provide textual content for elements that have a content model.
|
||||
auto before = element->get_pseudo_element_node(CSS::Selector::PseudoElement::Type::Before);
|
||||
auto after = element->get_pseudo_element_node(CSS::Selector::PseudoElement::Type::After);
|
||||
// - For :before pseudo elements, User agents MUST prepend CSS textual content, without a space, to the textual content of the current node.
|
||||
if (before)
|
||||
TRY(Node::prepend_without_space(total_accumulated_text, before->computed_values().content().data));
|
||||
|
||||
// - For :after pseudo elements, User agents MUST append CSS textual content, without a space, to the textual content of the current node.
|
||||
if (after)
|
||||
TRY(Node::append_without_space(total_accumulated_text, after->computed_values().content().data));
|
||||
|
||||
// ii. Name From Generated Content: Check for CSS generated textual content associated with the current node and include
|
||||
// it in the accumulated text. The CSS ::before and ::after pseudo elements [CSS2] can provide textual content for
|
||||
// elements that have a content model.
|
||||
// a. For ::before pseudo elements, User agents MUST prepend CSS textual content, without a space, to the textual
|
||||
// content of the current node.
|
||||
// b. For ::after pseudo elements, User agents MUST append CSS textual content, without a space, to the textual content
|
||||
// of the current node. NOTE: The code for handling the ::after pseudo elements case is further below,
|
||||
// following the “iii. For each child node of the current node” code.
|
||||
if (auto before = element->get_pseudo_element_node(CSS::Selector::PseudoElement::Type::Before)) {
|
||||
if (before->computed_values().content().alt_text.has_value())
|
||||
total_accumulated_text.append(before->computed_values().content().alt_text.release_value());
|
||||
else
|
||||
total_accumulated_text.append(before->computed_values().content().data);
|
||||
}
|
||||
// iii. For each child node of the current node:
|
||||
element->for_each_child([&total_accumulated_text, current_node, target, &document, &visited_nodes](
|
||||
DOM::Node const& child_node) mutable {
|
||||
|
@ -2377,8 +2380,14 @@ ErrorOr<String> Node::name_or_description(NameOrDescription target, Document con
|
|||
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
// NOTE: See step ii.b above.
|
||||
if (auto after = element->get_pseudo_element_node(CSS::Selector::PseudoElement::Type::After)) {
|
||||
if (after->computed_values().content().alt_text.has_value())
|
||||
total_accumulated_text.append(after->computed_values().content().alt_text.release_value());
|
||||
else
|
||||
total_accumulated_text.append(after->computed_values().content().data);
|
||||
}
|
||||
// v. Return the accumulated text if it is not the empty string ("").
|
||||
if (!total_accumulated_text.is_empty())
|
||||
return total_accumulated_text.to_string();
|
||||
// Important: Each node in the subtree is consulted only once. If text has been collected from a descendant, but is referenced by another IDREF in some descendant node, then that second, or subsequent, reference is not followed. This is done to avoid infinite loops.
|
||||
}
|
||||
|
|
|
@ -254,6 +254,7 @@ void TreeBuilder::create_pseudo_element_if_needed(DOM::Element& element, CSS::Se
|
|||
|
||||
element.set_pseudo_element_node({}, pseudo_element, pseudo_element_node);
|
||||
insert_node_into_inline_or_block_ancestor(*pseudo_element_node, pseudo_element_display, mode);
|
||||
pseudo_element_node->mutable_computed_values().set_content(pseudo_element_content);
|
||||
}
|
||||
|
||||
static bool is_ignorable_whitespace(Layout::Node const& node)
|
||||
|
|
Loading…
Reference in a new issue