mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-05 08:31:51 +00:00
LibWeb: Add explicit "active range" editing algorithm
This makes some of the spec implementations easier to follow and makes it extra clear that the range is optional.
This commit is contained in:
parent
2987dd1060
commit
85abad30b0
Notes:
github-actions[bot]
2025-01-10 22:38:46 +00:00
Author: https://github.com/gmta
Commit: 85abad30b0
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3216
2 changed files with 26 additions and 15 deletions
|
@ -37,6 +37,17 @@
|
|||
|
||||
namespace Web::Editing {
|
||||
|
||||
// https://w3c.github.io/editing/docs/execCommand/#active-range
|
||||
GC::Ptr<DOM::Range> active_range(DOM::Document const& document)
|
||||
{
|
||||
// The active range is the range of the selection given by calling getSelection() on the context object. (Thus the
|
||||
// active range may be null.)
|
||||
auto selection = document.get_selection();
|
||||
if (!selection)
|
||||
return {};
|
||||
return selection->range();
|
||||
}
|
||||
|
||||
// https://w3c.github.io/editing/docs/execCommand/#block-extend
|
||||
GC::Ref<DOM::Range> block_extend_a_range(GC::Ref<DOM::Range> range)
|
||||
{
|
||||
|
@ -463,21 +474,20 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
|||
|
||||
// 1. If the active range is null, abort these steps and do nothing.
|
||||
// NOTE: The selection is collapsed often in this algorithm, so we shouldn't store the active range in a variable.
|
||||
auto active_range = [&selection] { return selection.range(); };
|
||||
if (!active_range())
|
||||
if (!active_range(document))
|
||||
return;
|
||||
|
||||
// 2. Canonicalize whitespace at the active range's start.
|
||||
canonicalize_whitespace(active_range()->start());
|
||||
canonicalize_whitespace(active_range(document)->start());
|
||||
|
||||
// 3. Canonicalize whitespace at the active range's end.
|
||||
canonicalize_whitespace(active_range()->end());
|
||||
canonicalize_whitespace(active_range(document)->end());
|
||||
|
||||
// 4. Let (start node, start offset) be the last equivalent point for the active range's start.
|
||||
auto start = last_equivalent_point(active_range()->start());
|
||||
auto start = last_equivalent_point(active_range(document)->start());
|
||||
|
||||
// 5. Let (end node, end offset) be the first equivalent point for the active range's end.
|
||||
auto end = first_equivalent_point(active_range()->end());
|
||||
auto end = first_equivalent_point(active_range(document)->end());
|
||||
|
||||
// 6. If (end node, end offset) is not after (start node, start offset):
|
||||
auto relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point({ end.node, end.offset }, { start.node, start.offset });
|
||||
|
@ -521,7 +531,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
|||
MUST(selection.extend(end.node, end.offset));
|
||||
|
||||
// 12. Let start block be the active range's start node.
|
||||
GC::Ptr<DOM::Node> start_block = active_range()->start_container();
|
||||
GC::Ptr<DOM::Node> start_block = active_range(document)->start_container();
|
||||
|
||||
// 13. While start block's parent is in the same editing host and start block is an inline node, set start block to
|
||||
// its parent.
|
||||
|
@ -536,7 +546,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
|||
start_block = {};
|
||||
|
||||
// 15. Let end block be the active range's end node.
|
||||
GC::Ptr<DOM::Node> end_block = active_range()->end_container();
|
||||
GC::Ptr<DOM::Node> end_block = active_range(document)->end_container();
|
||||
|
||||
// 16. While end block's parent is in the same editing host and end block is an inline node, set end block to its
|
||||
// parent.
|
||||
|
@ -551,7 +561,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
|||
end_block = {};
|
||||
|
||||
// 19. Record current states and values, and let overrides be the result.
|
||||
auto overrides = record_current_states_and_values(*active_range());
|
||||
auto overrides = record_current_states_and_values(*active_range(document));
|
||||
|
||||
// 21. If start node and end node are the same, and start node is an editable Text node:
|
||||
if (start.node == end.node && is<DOM::Text>(*start.node) && start.node->is_editable()) {
|
||||
|
@ -588,7 +598,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
|||
|
||||
// 24. For each node contained in the active range, append node to node list if the last member of node list (if
|
||||
// any) is not an ancestor of node; node is editable; and node is not a thead, tbody, tfoot, tr, th, or td.
|
||||
active_range()->for_each_contained([&node_list](GC::Ref<DOM::Node> node) {
|
||||
active_range(document)->for_each_contained([&node_list](GC::Ref<DOM::Node> node) {
|
||||
if (!node_list.is_empty() && node_list.last()->is_ancestor_of(node))
|
||||
return IterationDecision::Continue;
|
||||
|
||||
|
@ -633,10 +643,10 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
|||
MUST(static_cast<DOM::Text&>(*end.node).delete_data(0, end.offset));
|
||||
|
||||
// 27. Canonicalize whitespace at the active range's start, with fix collapsed space false.
|
||||
canonicalize_whitespace(active_range()->start(), false);
|
||||
canonicalize_whitespace(active_range(document)->start(), false);
|
||||
|
||||
// 28. Canonicalize whitespace at the active range's end, with fix collapsed space false.
|
||||
canonicalize_whitespace(active_range()->end(), false);
|
||||
canonicalize_whitespace(active_range(document)->end(), false);
|
||||
|
||||
// 30. If block merging is false, or start block or end block is null, or start block is not in the same editing
|
||||
// host as end block, or start block and end block are the same:
|
||||
|
@ -702,7 +712,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
|||
end_block->remove();
|
||||
|
||||
// 4. Restore states and values from overrides.
|
||||
restore_states_and_values(*active_range(), overrides);
|
||||
restore_states_and_values(*active_range(document), overrides);
|
||||
|
||||
// 5. Abort these steps.
|
||||
return;
|
||||
|
@ -711,7 +721,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
|||
// 5. If end block's firstChild is not an inline node, restore states and values from record, then abort these
|
||||
// steps.
|
||||
if (!is_inline_node(*end_block->first_child())) {
|
||||
restore_states_and_values(*active_range(), overrides);
|
||||
restore_states_and_values(*active_range(document), overrides);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -873,7 +883,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
|||
remove_extraneous_line_breaks_at_the_end_of_node(*start_block);
|
||||
|
||||
// 41. Restore states and values from overrides.
|
||||
restore_states_and_values(*active_range(), overrides);
|
||||
restore_states_and_values(*active_range(document), overrides);
|
||||
}
|
||||
|
||||
// https://w3c.github.io/editing/docs/execCommand/#editing-host-of
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue