From e686328cbd8f9de26d0fc3f8f875ece34241db01 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Wed, 8 Jan 2025 17:38:02 +0100 Subject: [PATCH] LibWeb: Implement the "unlink" editing command --- Libraries/LibWeb/Editing/Commands.cpp | 40 +++++++++++++++++++ Libraries/LibWeb/Editing/Commands.h | 1 + .../expected/Editing/execCommand-unlink.txt | 2 + .../input/Editing/execCommand-unlink.html | 23 +++++++++++ 4 files changed, 66 insertions(+) create mode 100644 Tests/LibWeb/Text/expected/Editing/execCommand-unlink.txt create mode 100644 Tests/LibWeb/Text/input/Editing/execCommand-unlink.html diff --git a/Libraries/LibWeb/Editing/Commands.cpp b/Libraries/LibWeb/Editing/Commands.cpp index da74aed07f0..9ce787e7a22 100644 --- a/Libraries/LibWeb/Editing/Commands.cpp +++ b/Libraries/LibWeb/Editing/Commands.cpp @@ -1439,6 +1439,41 @@ bool command_underline_action(DOM::Document& document, String const&) return true; } +// https://w3c.github.io/editing/docs/execCommand/#the-unlink-command +bool command_unlink_action(DOM::Document& document, String const&) +{ + // 1. Let hyperlinks be a list of every a element that has an href attribute and is contained in the active range or + // is an ancestor of one of its boundary points. + Vector> hyperlinks; + if (auto range = active_range(document)) { + auto node_matches = [](GC::Ref node) { + return is(*node) + && static_cast(*node).has_attribute(HTML::AttributeNames::href); + }; + range->for_each_contained([&](GC::Ref node) { + if (node_matches(node)) + hyperlinks.append(static_cast(*node)); + return IterationDecision::Continue; + }); + auto add_matching_ancestors = [&](GC::Ref node) { + node->for_each_ancestor([&](GC::Ref ancestor) { + if (node_matches(ancestor)) + hyperlinks.append(static_cast(*ancestor)); + return IterationDecision::Continue; + }); + }; + add_matching_ancestors(range->start_container()); + add_matching_ancestors(range->end_container()); + } + + // 2. Clear the value of each member of hyperlinks. + for (auto member : hyperlinks) + clear_the_value(CommandNames::unlink, member); + + // 3. Return true. + return true; +} + static Array const commands { // https://w3c.github.io/editing/docs/execCommand/#the-backcolor-command CommandDefinition { @@ -1557,6 +1592,11 @@ static Array const commands { .action = command_underline_action, .inline_activated_values = { "underline"sv }, }, + // https://w3c.github.io/editing/docs/execCommand/#the-unlink-command + CommandDefinition { + .command = CommandNames::unlink, + .action = command_unlink_action, + }, }; Optional find_command_definition(FlyString const& command) diff --git a/Libraries/LibWeb/Editing/Commands.h b/Libraries/LibWeb/Editing/Commands.h index 971671ffa91..52326fa74d9 100644 --- a/Libraries/LibWeb/Editing/Commands.h +++ b/Libraries/LibWeb/Editing/Commands.h @@ -52,5 +52,6 @@ bool command_subscript_indeterminate(DOM::Document const&); bool command_superscript_action(DOM::Document&, String const&); bool command_superscript_indeterminate(DOM::Document const&); bool command_underline_action(DOM::Document&, String const&); +bool command_unlink_action(DOM::Document&, String const&); } diff --git a/Tests/LibWeb/Text/expected/Editing/execCommand-unlink.txt b/Tests/LibWeb/Text/expected/Editing/execCommand-unlink.txt new file mode 100644 index 00000000000..93660e0dfcc --- /dev/null +++ b/Tests/LibWeb/Text/expected/Editing/execCommand-unlink.txt @@ -0,0 +1,2 @@ +d1 contents: "ladybird" +d2 contents: "ladybird" diff --git a/Tests/LibWeb/Text/input/Editing/execCommand-unlink.html b/Tests/LibWeb/Text/input/Editing/execCommand-unlink.html new file mode 100644 index 00000000000..78058cf39b3 --- /dev/null +++ b/Tests/LibWeb/Text/input/Editing/execCommand-unlink.html @@ -0,0 +1,23 @@ + + +
ladybird
+