mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-10 01:59:31 +00:00
LibWeb: Add concept of boundary point to DOM::AbstractRange
This makes comparing the relative position of boundary points a bit nicer when one of the boundary points is the range's start or end.
This commit is contained in:
parent
a3b3f2f30d
commit
e6631a4216
Notes:
github-actions[bot]
2024-12-21 18:17:22 +00:00
Author: https://github.com/gmta
Commit: e6631a4216
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2991
7 changed files with 88 additions and 102 deletions
|
@ -13,6 +13,12 @@
|
||||||
|
|
||||||
namespace Web::DOM {
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
// https://dom.spec.whatwg.org/#concept-range-bp
|
||||||
|
struct BoundaryPoint {
|
||||||
|
GC::Ref<Node> node;
|
||||||
|
WebIDL::UnsignedLong offset;
|
||||||
|
};
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#abstractrange
|
// https://dom.spec.whatwg.org/#abstractrange
|
||||||
class AbstractRange : public Bindings::PlatformObject {
|
class AbstractRange : public Bindings::PlatformObject {
|
||||||
WEB_PLATFORM_OBJECT(AbstractRange, Bindings::PlatformObject);
|
WEB_PLATFORM_OBJECT(AbstractRange, Bindings::PlatformObject);
|
||||||
|
@ -20,9 +26,11 @@ class AbstractRange : public Bindings::PlatformObject {
|
||||||
public:
|
public:
|
||||||
virtual ~AbstractRange() override;
|
virtual ~AbstractRange() override;
|
||||||
|
|
||||||
|
BoundaryPoint start() const { return { m_start_container, m_start_offset }; }
|
||||||
GC::Ref<Node> start_container() const { return m_start_container; }
|
GC::Ref<Node> start_container() const { return m_start_container; }
|
||||||
WebIDL::UnsignedLong start_offset() const { return m_start_offset; }
|
WebIDL::UnsignedLong start_offset() const { return m_start_offset; }
|
||||||
|
|
||||||
|
BoundaryPoint end() const { return { m_end_container, m_end_offset }; }
|
||||||
GC::Ref<Node> end_container() const { return m_end_container; }
|
GC::Ref<Node> end_container() const { return m_end_container; }
|
||||||
WebIDL::UnsignedLong end_offset() const { return m_end_offset; }
|
WebIDL::UnsignedLong end_offset() const { return m_end_offset; }
|
||||||
|
|
||||||
|
|
|
@ -117,27 +117,27 @@ GC::Ref<Node> Range::root() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-range-bp-position
|
// https://dom.spec.whatwg.org/#concept-range-bp-position
|
||||||
RelativeBoundaryPointPosition position_of_boundary_point_relative_to_other_boundary_point(GC::Ref<Node> node_a, u32 offset_a, GC::Ref<Node> node_b, u32 offset_b)
|
RelativeBoundaryPointPosition position_of_boundary_point_relative_to_other_boundary_point(BoundaryPoint a, BoundaryPoint b)
|
||||||
{
|
{
|
||||||
// 1. Assert: nodeA and nodeB have the same root.
|
// 1. Assert: nodeA and nodeB have the same root.
|
||||||
// NOTE: Nodes may not share the same root if they belong to different shadow trees,
|
// NOTE: Nodes may not share the same root if they belong to different shadow trees,
|
||||||
// so we assert that they share the same shadow-including root instead.
|
// so we assert that they share the same shadow-including root instead.
|
||||||
VERIFY(&node_a->shadow_including_root() == &node_b->shadow_including_root());
|
VERIFY(&a.node->shadow_including_root() == &b.node->shadow_including_root());
|
||||||
|
|
||||||
// 2. If nodeA is nodeB, then return equal if offsetA is offsetB, before if offsetA is less than offsetB, and after if offsetA is greater than offsetB.
|
// 2. If nodeA is nodeB, then return equal if offsetA is offsetB, before if offsetA is less than offsetB, and after if offsetA is greater than offsetB.
|
||||||
if (node_a == node_b) {
|
if (a.node == b.node) {
|
||||||
if (offset_a == offset_b)
|
if (a.offset == b.offset)
|
||||||
return RelativeBoundaryPointPosition::Equal;
|
return RelativeBoundaryPointPosition::Equal;
|
||||||
|
|
||||||
if (offset_a < offset_b)
|
if (a.offset < b.offset)
|
||||||
return RelativeBoundaryPointPosition::Before;
|
return RelativeBoundaryPointPosition::Before;
|
||||||
|
|
||||||
return RelativeBoundaryPointPosition::After;
|
return RelativeBoundaryPointPosition::After;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. If nodeA is following nodeB, then if the position of (nodeB, offsetB) relative to (nodeA, offsetA) is before, return after, and if it is after, return before.
|
// 3. If nodeA is following nodeB, then if the position of (nodeB, offsetB) relative to (nodeA, offsetA) is before, return after, and if it is after, return before.
|
||||||
if (node_a->is_following(node_b)) {
|
if (a.node->is_following(b.node)) {
|
||||||
auto relative_position = position_of_boundary_point_relative_to_other_boundary_point(node_b, offset_b, node_a, offset_a);
|
auto relative_position = position_of_boundary_point_relative_to_other_boundary_point(b, a);
|
||||||
|
|
||||||
if (relative_position == RelativeBoundaryPointPosition::Before)
|
if (relative_position == RelativeBoundaryPointPosition::Before)
|
||||||
return RelativeBoundaryPointPosition::After;
|
return RelativeBoundaryPointPosition::After;
|
||||||
|
@ -147,19 +147,19 @@ RelativeBoundaryPointPosition position_of_boundary_point_relative_to_other_bound
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. If nodeA is an ancestor of nodeB:
|
// 4. If nodeA is an ancestor of nodeB:
|
||||||
if (node_a->is_ancestor_of(node_b)) {
|
if (a.node->is_ancestor_of(b.node)) {
|
||||||
// 1. Let child be nodeB.
|
// 1. Let child be nodeB.
|
||||||
GC::Ref<Node const> child = node_b;
|
GC::Ref<Node const> child = b.node;
|
||||||
|
|
||||||
// 2. While child is not a child of nodeA, set child to its parent.
|
// 2. While child is not a child of nodeA, set child to its parent.
|
||||||
while (!node_a->is_parent_of(child)) {
|
while (!a.node->is_parent_of(child)) {
|
||||||
auto* parent = child->parent();
|
auto* parent = child->parent();
|
||||||
VERIFY(parent);
|
VERIFY(parent);
|
||||||
child = *parent;
|
child = *parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. If child’s index is less than offsetA, then return after.
|
// 3. If child’s index is less than offsetA, then return after.
|
||||||
if (child->index() < offset_a)
|
if (child->index() < a.offset)
|
||||||
return RelativeBoundaryPointPosition::After;
|
return RelativeBoundaryPointPosition::After;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ WebIDL::ExceptionOr<void> Range::set_start_or_end(GC::Ref<Node> node, u32 offset
|
||||||
// -> If these steps were invoked as "set the start"
|
// -> If these steps were invoked as "set the start"
|
||||||
|
|
||||||
// 1. If range’s root is not equal to node’s root, or if bp is after the range’s end, set range’s end to bp.
|
// 1. If range’s root is not equal to node’s root, or if bp is after the range’s end, set range’s end to bp.
|
||||||
if (root().ptr() != &node->root() || position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_end_container, m_end_offset) == RelativeBoundaryPointPosition::After) {
|
if (root().ptr() != &node->root() || position_of_boundary_point_relative_to_other_boundary_point({ node, offset }, end()) == RelativeBoundaryPointPosition::After) {
|
||||||
m_end_container = node;
|
m_end_container = node;
|
||||||
m_end_offset = offset;
|
m_end_offset = offset;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ WebIDL::ExceptionOr<void> Range::set_start_or_end(GC::Ref<Node> node, u32 offset
|
||||||
VERIFY(start_or_end == StartOrEnd::End);
|
VERIFY(start_or_end == StartOrEnd::End);
|
||||||
|
|
||||||
// 1. If range’s root is not equal to node’s root, or if bp is before the range’s start, set range’s start to bp.
|
// 1. If range’s root is not equal to node’s root, or if bp is before the range’s start, set range’s start to bp.
|
||||||
if (root().ptr() != &node->root() || position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_start_container, m_start_offset) == RelativeBoundaryPointPosition::Before) {
|
if (root().ptr() != &node->root() || position_of_boundary_point_relative_to_other_boundary_point({ node, offset }, start()) == RelativeBoundaryPointPosition::Before) {
|
||||||
m_start_container = node;
|
m_start_container = node;
|
||||||
m_start_offset = offset;
|
m_start_offset = offset;
|
||||||
}
|
}
|
||||||
|
@ -349,7 +349,7 @@ WebIDL::ExceptionOr<WebIDL::Short> Range::compare_boundary_points(WebIDL::Unsign
|
||||||
VERIFY(other_point_node);
|
VERIFY(other_point_node);
|
||||||
|
|
||||||
// 4. If the position of this point relative to other point is
|
// 4. If the position of this point relative to other point is
|
||||||
auto relative_position = position_of_boundary_point_relative_to_other_boundary_point(*this_point_node, this_point_offset, *other_point_node, other_point_offset);
|
auto relative_position = position_of_boundary_point_relative_to_other_boundary_point({ *this_point_node, this_point_offset }, { *other_point_node, other_point_offset });
|
||||||
switch (relative_position) {
|
switch (relative_position) {
|
||||||
case RelativeBoundaryPointPosition::Before:
|
case RelativeBoundaryPointPosition::Before:
|
||||||
// -> before
|
// -> before
|
||||||
|
@ -492,11 +492,11 @@ bool Range::intersects_node(GC::Ref<Node> node) const
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// 4. Let offset be node’s index.
|
// 4. Let offset be node’s index.
|
||||||
auto offset = node->index();
|
WebIDL::UnsignedLong offset = node->index();
|
||||||
|
|
||||||
// 5. If (parent, offset) is before end and (parent, offset plus 1) is after start, return true
|
// 5. If (parent, offset) is before end and (parent, offset plus 1) is after start, return true
|
||||||
auto relative_position_to_end = position_of_boundary_point_relative_to_other_boundary_point(*parent, offset, m_end_container, m_end_offset);
|
auto relative_position_to_end = position_of_boundary_point_relative_to_other_boundary_point({ *parent, offset }, end());
|
||||||
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point(*parent, offset + 1, m_start_container, m_start_offset);
|
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point({ *parent, offset + 1 }, start());
|
||||||
if (relative_position_to_end == RelativeBoundaryPointPosition::Before && relative_position_to_start == RelativeBoundaryPointPosition::After)
|
if (relative_position_to_end == RelativeBoundaryPointPosition::Before && relative_position_to_start == RelativeBoundaryPointPosition::After)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -520,8 +520,8 @@ WebIDL::ExceptionOr<bool> Range::is_point_in_range(GC::Ref<Node> node, WebIDL::U
|
||||||
return WebIDL::IndexSizeError::create(realm(), MUST(String::formatted("Node does not contain a child at offset {}", offset)));
|
return WebIDL::IndexSizeError::create(realm(), MUST(String::formatted("Node does not contain a child at offset {}", offset)));
|
||||||
|
|
||||||
// 4. If (node, offset) is before start or after end, return false.
|
// 4. If (node, offset) is before start or after end, return false.
|
||||||
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_start_container, m_start_offset);
|
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point({ node, offset }, start());
|
||||||
auto relative_position_to_end = position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_end_container, m_end_offset);
|
auto relative_position_to_end = position_of_boundary_point_relative_to_other_boundary_point({ node, offset }, end());
|
||||||
if (relative_position_to_start == RelativeBoundaryPointPosition::Before || relative_position_to_end == RelativeBoundaryPointPosition::After)
|
if (relative_position_to_start == RelativeBoundaryPointPosition::Before || relative_position_to_end == RelativeBoundaryPointPosition::After)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -545,12 +545,12 @@ WebIDL::ExceptionOr<WebIDL::Short> Range::compare_point(GC::Ref<Node> node, WebI
|
||||||
return WebIDL::IndexSizeError::create(realm(), MUST(String::formatted("Node does not contain a child at offset {}", offset)));
|
return WebIDL::IndexSizeError::create(realm(), MUST(String::formatted("Node does not contain a child at offset {}", offset)));
|
||||||
|
|
||||||
// 4. If (node, offset) is before start, return −1.
|
// 4. If (node, offset) is before start, return −1.
|
||||||
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_start_container, m_start_offset);
|
auto relative_position_to_start = position_of_boundary_point_relative_to_other_boundary_point({ node, offset }, start());
|
||||||
if (relative_position_to_start == RelativeBoundaryPointPosition::Before)
|
if (relative_position_to_start == RelativeBoundaryPointPosition::Before)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// 5. If (node, offset) is after end, return 1.
|
// 5. If (node, offset) is after end, return 1.
|
||||||
auto relative_position_to_end = position_of_boundary_point_relative_to_other_boundary_point(node, offset, m_end_container, m_end_offset);
|
auto relative_position_to_end = position_of_boundary_point_relative_to_other_boundary_point({ node, offset }, end());
|
||||||
if (relative_position_to_end == RelativeBoundaryPointPosition::After)
|
if (relative_position_to_end == RelativeBoundaryPointPosition::After)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -794,11 +794,11 @@ bool Range::contains_node(GC::Ref<Node> node) const
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// and (node, 0) is after range’s start,
|
// and (node, 0) is after range’s start,
|
||||||
if (position_of_boundary_point_relative_to_other_boundary_point(node, 0, m_start_container, m_start_offset) != RelativeBoundaryPointPosition::After)
|
if (position_of_boundary_point_relative_to_other_boundary_point({ node, 0 }, start()) != RelativeBoundaryPointPosition::After)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// and (node, node’s length) is before range’s end.
|
// and (node, node’s length) is before range’s end.
|
||||||
if (position_of_boundary_point_relative_to_other_boundary_point(node, node->length(), m_end_container, m_end_offset) != RelativeBoundaryPointPosition::Before)
|
if (position_of_boundary_point_relative_to_other_boundary_point({ node, static_cast<WebIDL::UnsignedLong>(node->length()) }, end()) != RelativeBoundaryPointPosition::Before)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -22,7 +22,7 @@ enum class RelativeBoundaryPointPosition {
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-range-bp-position
|
// https://dom.spec.whatwg.org/#concept-range-bp-position
|
||||||
RelativeBoundaryPointPosition position_of_boundary_point_relative_to_other_boundary_point(GC::Ref<Node> node_a, u32 offset_a, GC::Ref<Node> node_b, u32 offset_b);
|
RelativeBoundaryPointPosition position_of_boundary_point_relative_to_other_boundary_point(BoundaryPoint a, BoundaryPoint b);
|
||||||
|
|
||||||
class Range final : public AbstractRange {
|
class Range final : public AbstractRange {
|
||||||
WEB_PLATFORM_OBJECT(Range, AbstractRange);
|
WEB_PLATFORM_OBJECT(Range, AbstractRange);
|
||||||
|
|
|
@ -65,7 +65,7 @@ bool command_delete_action(DOM::Document& document, String const&)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Canonicalize whitespace at the active range's start.
|
// 2. Canonicalize whitespace at the active range's start.
|
||||||
canonicalize_whitespace(active_range.start_container(), active_range.start_offset());
|
canonicalize_whitespace(active_range.start());
|
||||||
|
|
||||||
// 3. Let node and offset be the active range's start node and offset.
|
// 3. Let node and offset be the active range's start node and offset.
|
||||||
GC::Ptr<DOM::Node> node = active_range.start_container();
|
GC::Ptr<DOM::Node> node = active_range.start_container();
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <LibWeb/DOM/DocumentType.h>
|
#include <LibWeb/DOM/DocumentType.h>
|
||||||
#include <LibWeb/DOM/Element.h>
|
#include <LibWeb/DOM/Element.h>
|
||||||
#include <LibWeb/DOM/ElementFactory.h>
|
#include <LibWeb/DOM/ElementFactory.h>
|
||||||
#include <LibWeb/DOM/Range.h>
|
|
||||||
#include <LibWeb/DOM/Text.h>
|
#include <LibWeb/DOM/Text.h>
|
||||||
#include <LibWeb/Editing/CommandNames.h>
|
#include <LibWeb/Editing/CommandNames.h>
|
||||||
#include <LibWeb/Editing/Commands.h>
|
#include <LibWeb/Editing/Commands.h>
|
||||||
|
@ -60,7 +59,7 @@ GC::Ref<DOM::Range> block_extend_a_range(DOM::Range& range)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. If (start node, start offset) is not a block start point, repeat the following steps:
|
// 3. If (start node, start offset) is not a block start point, repeat the following steps:
|
||||||
if (!is_block_start_point(*start_node, start_offset)) {
|
if (!is_block_start_point({ *start_node, start_offset })) {
|
||||||
do {
|
do {
|
||||||
// 1. If start offset is zero, set it to start node's index, then set start node to its parent.
|
// 1. If start offset is zero, set it to start node's index, then set start node to its parent.
|
||||||
if (start_offset == 0) {
|
if (start_offset == 0) {
|
||||||
|
@ -74,7 +73,7 @@ GC::Ref<DOM::Range> block_extend_a_range(DOM::Range& range)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. If (start node, start offset) is a block boundary point, break from this loop.
|
// 3. If (start node, start offset) is a block boundary point, break from this loop.
|
||||||
} while (!is_block_boundary_point(*start_node, start_offset));
|
} while (!is_block_boundary_point({ *start_node, start_offset }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. While start offset is zero and start node's parent is not null, set start offset to start node's index, then
|
// 4. While start offset is zero and start node's parent is not null, set start offset to start node's index, then
|
||||||
|
@ -97,7 +96,7 @@ GC::Ref<DOM::Range> block_extend_a_range(DOM::Range& range)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. If (end node, end offset) is not a block end point, repeat the following steps:
|
// 6. If (end node, end offset) is not a block end point, repeat the following steps:
|
||||||
if (!is_block_end_point(*end_node, end_offset)) {
|
if (!is_block_end_point({ *end_node, end_offset })) {
|
||||||
do {
|
do {
|
||||||
// 1. If end offset is end node's length, set it to one plus end node's index, then set end node to its
|
// 1. If end offset is end node's length, set it to one plus end node's index, then set end node to its
|
||||||
// parent.
|
// parent.
|
||||||
|
@ -112,7 +111,7 @@ GC::Ref<DOM::Range> block_extend_a_range(DOM::Range& range)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. If (end node, end offset) is a block boundary point, break from this loop.
|
// 3. If (end node, end offset) is a block boundary point, break from this loop.
|
||||||
} while (!is_block_boundary_point(*end_node, end_offset));
|
} while (!is_block_boundary_point({ *end_node, end_offset }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. While end offset is end node's length and end node's parent is not null, set end offset to one plus end node's
|
// 7. While end offset is end node's length and end node's parent is not null, set end offset to one plus end node's
|
||||||
|
@ -222,8 +221,11 @@ String canonical_space_sequence(u32 length, bool non_breaking_start, bool non_br
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#canonicalize-whitespace
|
// https://w3c.github.io/editing/docs/execCommand/#canonicalize-whitespace
|
||||||
void canonicalize_whitespace(GC::Ref<DOM::Node> node, u32 offset, bool fix_collapsed_space)
|
void canonicalize_whitespace(DOM::BoundaryPoint boundary, bool fix_collapsed_space)
|
||||||
{
|
{
|
||||||
|
auto node = boundary.node;
|
||||||
|
auto offset = boundary.offset;
|
||||||
|
|
||||||
// 1. If node is neither editable nor an editing host, abort these steps.
|
// 1. If node is neither editable nor an editing host, abort these steps.
|
||||||
if (!node->is_editable_or_editing_host())
|
if (!node->is_editable_or_editing_host())
|
||||||
return;
|
return;
|
||||||
|
@ -349,7 +351,7 @@ void canonicalize_whitespace(GC::Ref<DOM::Node> node, u32 offset, bool fix_colla
|
||||||
// end offset):
|
// end offset):
|
||||||
if (fix_collapsed_space) {
|
if (fix_collapsed_space) {
|
||||||
while (true) {
|
while (true) {
|
||||||
auto relative_position = position_of_boundary_point_relative_to_other_boundary_point(*start_node, start_offset, *end_node, end_offset);
|
auto relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point({ *start_node, start_offset }, { *end_node, end_offset });
|
||||||
if (relative_position != DOM::RelativeBoundaryPointPosition::Before)
|
if (relative_position != DOM::RelativeBoundaryPointPosition::Before)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -408,7 +410,7 @@ void canonicalize_whitespace(GC::Ref<DOM::Node> node, u32 offset, bool fix_colla
|
||||||
|
|
||||||
// 10. While (start node, start offset) is before (end node, end offset):
|
// 10. While (start node, start offset) is before (end node, end offset):
|
||||||
while (true) {
|
while (true) {
|
||||||
auto relative_position = position_of_boundary_point_relative_to_other_boundary_point(start_node, start_offset, end_node, end_offset);
|
auto relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point({ start_node, start_offset }, { end_node, end_offset });
|
||||||
if (relative_position != DOM::RelativeBoundaryPointPosition::Before)
|
if (relative_position != DOM::RelativeBoundaryPointPosition::Before)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -468,19 +470,19 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// 2. Canonicalize whitespace at the active range's start.
|
// 2. Canonicalize whitespace at the active range's start.
|
||||||
canonicalize_whitespace(active_range()->start_container(), active_range()->start_offset());
|
canonicalize_whitespace(active_range()->start());
|
||||||
|
|
||||||
// 3. Canonicalize whitespace at the active range's end.
|
// 3. Canonicalize whitespace at the active range's end.
|
||||||
canonicalize_whitespace(active_range()->end_container(), active_range()->end_offset());
|
canonicalize_whitespace(active_range()->end());
|
||||||
|
|
||||||
// 4. Let (start node, start offset) be the last equivalent point for the active range's start.
|
// 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_container(), active_range()->start_offset() });
|
auto start = last_equivalent_point(active_range()->start());
|
||||||
|
|
||||||
// 5. Let (end node, end offset) be the first equivalent point for the active range's end.
|
// 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_container(), active_range()->end_offset() });
|
auto end = first_equivalent_point(active_range()->end());
|
||||||
|
|
||||||
// 6. If (end node, end offset) is not after (start node, start offset):
|
// 6. If (end node, end offset) is not after (start node, start offset):
|
||||||
auto relative_position = position_of_boundary_point_relative_to_other_boundary_point(end.node, end.offset, 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 });
|
||||||
if (relative_position != DOM::RelativeBoundaryPointPosition::After) {
|
if (relative_position != DOM::RelativeBoundaryPointPosition::After) {
|
||||||
// 1. If direction is "forward", call collapseToStart() on the context object's selection.
|
// 1. If direction is "forward", call collapseToStart() on the context object's selection.
|
||||||
if (direction == Selection::Direction::Forwards) {
|
if (direction == Selection::Direction::Forwards) {
|
||||||
|
@ -559,7 +561,7 @@ void delete_the_selection(Selection& selection, bool block_merging, bool strip_w
|
||||||
MUST(static_cast<DOM::Text&>(*start.node).delete_data(start.offset, end.offset - start.offset));
|
MUST(static_cast<DOM::Text&>(*start.node).delete_data(start.offset, end.offset - start.offset));
|
||||||
|
|
||||||
// 2. Canonicalize whitespace at (start node, start offset), with fix collapsed space false.
|
// 2. Canonicalize whitespace at (start node, start offset), with fix collapsed space false.
|
||||||
canonicalize_whitespace(start.node, start.offset, false);
|
canonicalize_whitespace(start, false);
|
||||||
|
|
||||||
// 3. If direction is "forward", call collapseToStart() on the context object's selection.
|
// 3. If direction is "forward", call collapseToStart() on the context object's selection.
|
||||||
if (direction == Selection::Direction::Forwards) {
|
if (direction == Selection::Direction::Forwards) {
|
||||||
|
@ -637,10 +639,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));
|
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.
|
// 27. Canonicalize whitespace at the active range's start, with fix collapsed space false.
|
||||||
canonicalize_whitespace(active_range()->start_container(), active_range()->start_offset(), false);
|
canonicalize_whitespace(active_range()->start(), false);
|
||||||
|
|
||||||
// 28. Canonicalize whitespace at the active range's end, with fix collapsed space false.
|
// 28. Canonicalize whitespace at the active range's end, with fix collapsed space false.
|
||||||
canonicalize_whitespace(active_range()->end_container(), active_range()->end_offset(), false);
|
canonicalize_whitespace(active_range()->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
|
// 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:
|
// host as end block, or start block and end block are the same:
|
||||||
|
@ -1046,7 +1048,7 @@ Optional<String> effective_command_value(GC::Ptr<DOM::Node> node, FlyString cons
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#first-equivalent-point
|
// https://w3c.github.io/editing/docs/execCommand/#first-equivalent-point
|
||||||
BoundaryPoint first_equivalent_point(BoundaryPoint boundary_point)
|
DOM::BoundaryPoint first_equivalent_point(DOM::BoundaryPoint boundary_point)
|
||||||
{
|
{
|
||||||
// 1. While (node, offset)'s previous equivalent point is not null, set (node, offset) to its previous equivalent
|
// 1. While (node, offset)'s previous equivalent point is not null, set (node, offset) to its previous equivalent
|
||||||
// point.
|
// point.
|
||||||
|
@ -1146,10 +1148,10 @@ void fix_disallowed_ancestors_of_node(GC::Ref<DOM::Node> node)
|
||||||
bool follows_a_line_break(GC::Ref<DOM::Node> node)
|
bool follows_a_line_break(GC::Ref<DOM::Node> node)
|
||||||
{
|
{
|
||||||
// 1. Let offset be zero.
|
// 1. Let offset be zero.
|
||||||
auto offset = 0;
|
auto offset = 0u;
|
||||||
|
|
||||||
// 2. While (node, offset) is not a block boundary point:
|
// 2. While (node, offset) is not a block boundary point:
|
||||||
while (!is_block_boundary_point(node, offset)) {
|
while (!is_block_boundary_point({ node, offset })) {
|
||||||
// 1. If node has a visible child with index offset minus one, return false.
|
// 1. If node has a visible child with index offset minus one, return false.
|
||||||
auto* offset_minus_one_child = node->child_at_index(offset - 1);
|
auto* offset_minus_one_child = node->child_at_index(offset - 1);
|
||||||
if (offset_minus_one_child && is_visible_node(*offset_minus_one_child))
|
if (offset_minus_one_child && is_visible_node(*offset_minus_one_child))
|
||||||
|
@ -1385,22 +1387,22 @@ bool is_allowed_child_of_node(Variant<GC::Ref<DOM::Node>, FlyString> child, Vari
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#block-boundary-point
|
// https://w3c.github.io/editing/docs/execCommand/#block-boundary-point
|
||||||
bool is_block_boundary_point(GC::Ref<DOM::Node> node, u32 offset)
|
bool is_block_boundary_point(DOM::BoundaryPoint boundary_point)
|
||||||
{
|
{
|
||||||
// A boundary point is a block boundary point if it is either a block start point or a block end point.
|
// A boundary point is a block boundary point if it is either a block start point or a block end point.
|
||||||
return is_block_start_point(node, offset) || is_block_end_point(node, offset);
|
return is_block_start_point(boundary_point) || is_block_end_point(boundary_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#block-end-point
|
// https://w3c.github.io/editing/docs/execCommand/#block-end-point
|
||||||
bool is_block_end_point(GC::Ref<DOM::Node> node, u32 offset)
|
bool is_block_end_point(DOM::BoundaryPoint boundary_point)
|
||||||
{
|
{
|
||||||
// A boundary point (node, offset) is a block end point if either node's parent is null and
|
// A boundary point (node, offset) is a block end point if either node's parent is null and
|
||||||
// offset is node's length;
|
// offset is node's length;
|
||||||
if (!node->parent() && offset == node->length())
|
if (!boundary_point.node->parent() && boundary_point.offset == boundary_point.node->length())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// or node has a child with index offset, and that child is a visible block node.
|
// or node has a child with index offset, and that child is a visible block node.
|
||||||
auto offset_child = node->child_at_index(offset);
|
auto offset_child = boundary_point.node->child_at_index(boundary_point.offset);
|
||||||
return offset_child && is_visible_node(*offset_child) && is_block_node(*offset_child);
|
return offset_child && is_visible_node(*offset_child) && is_block_node(*offset_child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1423,19 +1425,17 @@ bool is_block_node(GC::Ref<DOM::Node> node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#block-start-point
|
// https://w3c.github.io/editing/docs/execCommand/#block-start-point
|
||||||
bool is_block_start_point(GC::Ref<DOM::Node> node, u32 offset)
|
bool is_block_start_point(DOM::BoundaryPoint boundary_point)
|
||||||
{
|
{
|
||||||
// A boundary point (node, offset) is a block start point if either node's parent is null and
|
// A boundary point (node, offset) is a block start point if either node's parent is null and
|
||||||
// offset is zero;
|
// offset is zero;
|
||||||
if (!node->parent() && offset == 0)
|
if (!boundary_point.node->parent() && boundary_point.offset == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// or node has a child with index offset − 1, and that child is either a visible block node or a
|
// or node has a child with index offset − 1, and that child is either a visible block node or a
|
||||||
// visible br.
|
// visible br.
|
||||||
auto offset_minus_one_child = node->child_at_index(offset - 1);
|
auto offset_minus_one_child = boundary_point.node->child_at_index(boundary_point.offset - 1);
|
||||||
if (!offset_minus_one_child)
|
return offset_minus_one_child && is_visible_node(*offset_minus_one_child)
|
||||||
return false;
|
|
||||||
return is_visible_node(*offset_minus_one_child)
|
|
||||||
&& (is_block_node(*offset_minus_one_child) || is<HTML::HTMLBRElement>(*offset_minus_one_child));
|
&& (is_block_node(*offset_minus_one_child) || is<HTML::HTMLBRElement>(*offset_minus_one_child));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1893,7 +1893,7 @@ bool is_whitespace_node(GC::Ref<DOM::Node> node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#last-equivalent-point
|
// https://w3c.github.io/editing/docs/execCommand/#last-equivalent-point
|
||||||
BoundaryPoint last_equivalent_point(BoundaryPoint boundary_point)
|
DOM::BoundaryPoint last_equivalent_point(DOM::BoundaryPoint boundary_point)
|
||||||
{
|
{
|
||||||
// 1. While (node, offset)'s next equivalent point is not null, set (node, offset) to its next equivalent point.
|
// 1. While (node, offset)'s next equivalent point is not null, set (node, offset) to its next equivalent point.
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -1941,7 +1941,7 @@ void move_node_preserving_ranges(GC::Ref<DOM::Node> node, GC::Ref<DOM::Node> new
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#next-equivalent-point
|
// https://w3c.github.io/editing/docs/execCommand/#next-equivalent-point
|
||||||
Optional<BoundaryPoint> next_equivalent_point(BoundaryPoint boundary_point)
|
Optional<DOM::BoundaryPoint> next_equivalent_point(DOM::BoundaryPoint boundary_point)
|
||||||
{
|
{
|
||||||
// 1. If node's length is zero, return null.
|
// 1. If node's length is zero, return null.
|
||||||
auto node = boundary_point.node;
|
auto node = boundary_point.node;
|
||||||
|
@ -1952,13 +1952,13 @@ Optional<BoundaryPoint> next_equivalent_point(BoundaryPoint boundary_point)
|
||||||
// 3. If offset is node's length, and node's parent is not null, and node is an inline node, return (node's parent,
|
// 3. If offset is node's length, and node's parent is not null, and node is an inline node, return (node's parent,
|
||||||
// 1 + node's index).
|
// 1 + node's index).
|
||||||
if (boundary_point.offset == node_length && node->parent() && is_inline_node(*node))
|
if (boundary_point.offset == node_length && node->parent() && is_inline_node(*node))
|
||||||
return BoundaryPoint { *node->parent(), static_cast<WebIDL::UnsignedLong>(node->index() + 1) };
|
return DOM::BoundaryPoint { *node->parent(), static_cast<WebIDL::UnsignedLong>(node->index() + 1) };
|
||||||
|
|
||||||
// 5. If node has a child with index offset, and that child's length is not zero, and that child is an inline node,
|
// 5. If node has a child with index offset, and that child's length is not zero, and that child is an inline node,
|
||||||
// return (that child, 0).
|
// return (that child, 0).
|
||||||
auto child_at_offset = node->child_at_index(boundary_point.offset);
|
auto child_at_offset = node->child_at_index(boundary_point.offset);
|
||||||
if (child_at_offset && child_at_offset->length() != 0 && is_inline_node(*child_at_offset))
|
if (child_at_offset && child_at_offset->length() != 0 && is_inline_node(*child_at_offset))
|
||||||
return BoundaryPoint { *child_at_offset, 0 };
|
return DOM::BoundaryPoint { *child_at_offset, 0 };
|
||||||
|
|
||||||
// 7. Return null.
|
// 7. Return null.
|
||||||
return {};
|
return {};
|
||||||
|
@ -2014,10 +2014,10 @@ void normalize_sublists_in_node(GC::Ref<DOM::Element> item)
|
||||||
bool precedes_a_line_break(GC::Ref<DOM::Node> node)
|
bool precedes_a_line_break(GC::Ref<DOM::Node> node)
|
||||||
{
|
{
|
||||||
// 1. Let offset be node's length.
|
// 1. Let offset be node's length.
|
||||||
auto offset = node->length();
|
WebIDL::UnsignedLong offset = node->length();
|
||||||
|
|
||||||
// 2. While (node, offset) is not a block boundary point:
|
// 2. While (node, offset) is not a block boundary point:
|
||||||
while (!is_block_boundary_point(node, offset)) {
|
while (!is_block_boundary_point({ node, offset })) {
|
||||||
// 1. If node has a visible child with index offset, return false.
|
// 1. If node has a visible child with index offset, return false.
|
||||||
auto* offset_child = node->child_at_index(offset);
|
auto* offset_child = node->child_at_index(offset);
|
||||||
if (offset_child && is_visible_node(*offset_child))
|
if (offset_child && is_visible_node(*offset_child))
|
||||||
|
@ -2042,7 +2042,7 @@ bool precedes_a_line_break(GC::Ref<DOM::Node> node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#previous-equivalent-point
|
// https://w3c.github.io/editing/docs/execCommand/#previous-equivalent-point
|
||||||
Optional<BoundaryPoint> previous_equivalent_point(BoundaryPoint boundary_point)
|
Optional<DOM::BoundaryPoint> previous_equivalent_point(DOM::BoundaryPoint boundary_point)
|
||||||
{
|
{
|
||||||
// 1. If node's length is zero, return null.
|
// 1. If node's length is zero, return null.
|
||||||
auto node = boundary_point.node;
|
auto node = boundary_point.node;
|
||||||
|
@ -2053,13 +2053,13 @@ Optional<BoundaryPoint> previous_equivalent_point(BoundaryPoint boundary_point)
|
||||||
// 2. If offset is 0, and node's parent is not null, and node is an inline node, return (node's parent, node's
|
// 2. If offset is 0, and node's parent is not null, and node is an inline node, return (node's parent, node's
|
||||||
// index).
|
// index).
|
||||||
if (boundary_point.offset == 0 && node->parent() && is_inline_node(*node))
|
if (boundary_point.offset == 0 && node->parent() && is_inline_node(*node))
|
||||||
return BoundaryPoint { *node->parent(), static_cast<WebIDL::UnsignedLong>(node->index()) };
|
return DOM::BoundaryPoint { *node->parent(), static_cast<WebIDL::UnsignedLong>(node->index()) };
|
||||||
|
|
||||||
// 3. If node has a child with index offset − 1, and that child's length is not zero, and that child is an inline
|
// 3. If node has a child with index offset − 1, and that child's length is not zero, and that child is an inline
|
||||||
// node, return (that child, that child's length).
|
// node, return (that child, that child's length).
|
||||||
auto child_at_offset = node->child_at_index(boundary_point.offset - 1);
|
auto child_at_offset = node->child_at_index(boundary_point.offset - 1);
|
||||||
if (child_at_offset && child_at_offset->length() != 0 && is_inline_node(*child_at_offset))
|
if (child_at_offset && child_at_offset->length() != 0 && is_inline_node(*child_at_offset))
|
||||||
return BoundaryPoint { *child_at_offset, static_cast<WebIDL::UnsignedLong>(child_at_offset->length()) };
|
return DOM::BoundaryPoint { *child_at_offset, static_cast<WebIDL::UnsignedLong>(child_at_offset->length()) };
|
||||||
|
|
||||||
// 4. Return null.
|
// 4. Return null.
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibWeb/DOM/Node.h>
|
#include <LibWeb/DOM/Node.h>
|
||||||
|
#include <LibWeb/DOM/Range.h>
|
||||||
#include <LibWeb/Selection/Selection.h>
|
#include <LibWeb/Selection/Selection.h>
|
||||||
|
|
||||||
namespace Web::Editing {
|
namespace Web::Editing {
|
||||||
|
@ -27,32 +28,25 @@ struct RecordedOverride {
|
||||||
|
|
||||||
using Selection::Selection;
|
using Selection::Selection;
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#concept-range-bp
|
|
||||||
// FIXME: This should be defined by DOM::Range
|
|
||||||
struct BoundaryPoint {
|
|
||||||
GC::Ref<DOM::Node> node;
|
|
||||||
WebIDL::UnsignedLong offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Below algorithms are specified here:
|
// Below algorithms are specified here:
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#assorted-common-algorithms
|
// https://w3c.github.io/editing/docs/execCommand/#assorted-common-algorithms
|
||||||
|
|
||||||
GC::Ref<DOM::Range> block_extend_a_range(DOM::Range&);
|
GC::Ref<DOM::Range> block_extend_a_range(DOM::Range&);
|
||||||
GC::Ptr<DOM::Node> block_node_of_node(GC::Ref<DOM::Node>);
|
GC::Ptr<DOM::Node> block_node_of_node(GC::Ref<DOM::Node>);
|
||||||
String canonical_space_sequence(u32 length, bool non_breaking_start, bool non_breaking_end);
|
String canonical_space_sequence(u32 length, bool non_breaking_start, bool non_breaking_end);
|
||||||
void canonicalize_whitespace(GC::Ref<DOM::Node>, u32 offset, bool fix_collapsed_space = true);
|
void canonicalize_whitespace(DOM::BoundaryPoint, bool fix_collapsed_space = true);
|
||||||
void delete_the_selection(Selection&, bool block_merging = true, bool strip_wrappers = true,
|
void delete_the_selection(Selection&, bool block_merging = true, bool strip_wrappers = true,
|
||||||
Selection::Direction direction = Selection::Direction::Forwards);
|
Selection::Direction direction = Selection::Direction::Forwards);
|
||||||
GC::Ptr<DOM::Node> editing_host_of_node(GC::Ref<DOM::Node>);
|
GC::Ptr<DOM::Node> editing_host_of_node(GC::Ref<DOM::Node>);
|
||||||
Optional<String> effective_command_value(GC::Ptr<DOM::Node>, FlyString const& command);
|
Optional<String> effective_command_value(GC::Ptr<DOM::Node>, FlyString const& command);
|
||||||
BoundaryPoint first_equivalent_point(BoundaryPoint);
|
DOM::BoundaryPoint first_equivalent_point(DOM::BoundaryPoint);
|
||||||
void fix_disallowed_ancestors_of_node(GC::Ref<DOM::Node>);
|
void fix_disallowed_ancestors_of_node(GC::Ref<DOM::Node>);
|
||||||
bool follows_a_line_break(GC::Ref<DOM::Node>);
|
bool follows_a_line_break(GC::Ref<DOM::Node>);
|
||||||
bool is_allowed_child_of_node(Variant<GC::Ref<DOM::Node>, FlyString> child, Variant<GC::Ref<DOM::Node>, FlyString> parent);
|
bool is_allowed_child_of_node(Variant<GC::Ref<DOM::Node>, FlyString> child, Variant<GC::Ref<DOM::Node>, FlyString> parent);
|
||||||
bool is_block_boundary_point(GC::Ref<DOM::Node>, u32 offset);
|
bool is_block_boundary_point(DOM::BoundaryPoint);
|
||||||
bool is_block_end_point(GC::Ref<DOM::Node>, u32 offset);
|
bool is_block_end_point(DOM::BoundaryPoint);
|
||||||
bool is_block_node(GC::Ref<DOM::Node>);
|
bool is_block_node(GC::Ref<DOM::Node>);
|
||||||
bool is_block_start_point(GC::Ref<DOM::Node>, u32 offset);
|
bool is_block_start_point(DOM::BoundaryPoint);
|
||||||
bool is_collapsed_block_prop(GC::Ref<DOM::Node>);
|
bool is_collapsed_block_prop(GC::Ref<DOM::Node>);
|
||||||
bool is_collapsed_line_break(GC::Ref<DOM::Node>);
|
bool is_collapsed_line_break(GC::Ref<DOM::Node>);
|
||||||
bool is_collapsed_whitespace_node(GC::Ref<DOM::Node>);
|
bool is_collapsed_whitespace_node(GC::Ref<DOM::Node>);
|
||||||
|
@ -70,12 +64,12 @@ bool is_prohibited_paragraph_child_name(FlyString const&);
|
||||||
bool is_single_line_container(GC::Ref<DOM::Node>);
|
bool is_single_line_container(GC::Ref<DOM::Node>);
|
||||||
bool is_visible_node(GC::Ref<DOM::Node>);
|
bool is_visible_node(GC::Ref<DOM::Node>);
|
||||||
bool is_whitespace_node(GC::Ref<DOM::Node>);
|
bool is_whitespace_node(GC::Ref<DOM::Node>);
|
||||||
BoundaryPoint last_equivalent_point(BoundaryPoint);
|
DOM::BoundaryPoint last_equivalent_point(DOM::BoundaryPoint);
|
||||||
void move_node_preserving_ranges(GC::Ref<DOM::Node>, GC::Ref<DOM::Node> new_parent, u32 new_index);
|
void move_node_preserving_ranges(GC::Ref<DOM::Node>, GC::Ref<DOM::Node> new_parent, u32 new_index);
|
||||||
Optional<BoundaryPoint> next_equivalent_point(BoundaryPoint);
|
Optional<DOM::BoundaryPoint> next_equivalent_point(DOM::BoundaryPoint);
|
||||||
void normalize_sublists_in_node(GC::Ref<DOM::Element>);
|
void normalize_sublists_in_node(GC::Ref<DOM::Element>);
|
||||||
bool precedes_a_line_break(GC::Ref<DOM::Node>);
|
bool precedes_a_line_break(GC::Ref<DOM::Node>);
|
||||||
Optional<BoundaryPoint> previous_equivalent_point(BoundaryPoint);
|
Optional<DOM::BoundaryPoint> previous_equivalent_point(DOM::BoundaryPoint);
|
||||||
Vector<RecordedOverride> record_current_states_and_values(GC::Ref<DOM::Range>);
|
Vector<RecordedOverride> record_current_states_and_values(GC::Ref<DOM::Range>);
|
||||||
Vector<RecordedNodeValue> record_the_values_of_nodes(Vector<GC::Ref<DOM::Node>> const&);
|
Vector<RecordedNodeValue> record_the_values_of_nodes(Vector<GC::Ref<DOM::Node>> const&);
|
||||||
void remove_extraneous_line_breaks_at_the_end_of_node(GC::Ref<DOM::Node>);
|
void remove_extraneous_line_breaks_at_the_end_of_node(GC::Ref<DOM::Node>);
|
||||||
|
|
|
@ -296,7 +296,7 @@ WebIDL::ExceptionOr<void> Selection::extend(GC::Ref<DOM::Node> node, unsigned of
|
||||||
TRY(new_range->set_end(new_focus_node, new_focus_offset));
|
TRY(new_range->set_end(new_focus_node, new_focus_offset));
|
||||||
}
|
}
|
||||||
// 6. Otherwise, if oldAnchor is before or equal to newFocus, set the start newRange's start to oldAnchor, then set its end to newFocus.
|
// 6. Otherwise, if oldAnchor is before or equal to newFocus, set the start newRange's start to oldAnchor, then set its end to newFocus.
|
||||||
else if (position_of_boundary_point_relative_to_other_boundary_point(old_anchor_node, old_anchor_offset, new_focus_node, new_focus_offset) != DOM::RelativeBoundaryPointPosition::After) {
|
else if (DOM::position_of_boundary_point_relative_to_other_boundary_point({ old_anchor_node, old_anchor_offset }, { new_focus_node, new_focus_offset }) != DOM::RelativeBoundaryPointPosition::After) {
|
||||||
TRY(new_range->set_start(old_anchor_node, old_anchor_offset));
|
TRY(new_range->set_start(old_anchor_node, old_anchor_offset));
|
||||||
TRY(new_range->set_end(new_focus_node, new_focus_offset));
|
TRY(new_range->set_end(new_focus_node, new_focus_offset));
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ WebIDL::ExceptionOr<void> Selection::extend(GC::Ref<DOM::Node> node, unsigned of
|
||||||
set_range(new_range);
|
set_range(new_range);
|
||||||
|
|
||||||
// 9. If newFocus is before oldAnchor, set this's direction to backwards. Otherwise, set it to forwards.
|
// 9. If newFocus is before oldAnchor, set this's direction to backwards. Otherwise, set it to forwards.
|
||||||
if (position_of_boundary_point_relative_to_other_boundary_point(new_focus_node, new_focus_offset, old_anchor_node, old_anchor_offset) == DOM::RelativeBoundaryPointPosition::Before) {
|
if (DOM::position_of_boundary_point_relative_to_other_boundary_point({ new_focus_node, new_focus_offset }, { old_anchor_node, old_anchor_offset }) == DOM::RelativeBoundaryPointPosition::Before) {
|
||||||
m_direction = Direction::Backwards;
|
m_direction = Direction::Backwards;
|
||||||
} else {
|
} else {
|
||||||
m_direction = Direction::Forwards;
|
m_direction = Direction::Forwards;
|
||||||
|
@ -339,7 +339,7 @@ WebIDL::ExceptionOr<void> Selection::set_base_and_extent(GC::Ref<DOM::Node> anch
|
||||||
auto new_range = DOM::Range::create(*m_document);
|
auto new_range = DOM::Range::create(*m_document);
|
||||||
|
|
||||||
// 5. If anchor is before focus, set the start the newRange's start to anchor and its end to focus. Otherwise, set the start them to focus and anchor respectively.
|
// 5. If anchor is before focus, set the start the newRange's start to anchor and its end to focus. Otherwise, set the start them to focus and anchor respectively.
|
||||||
auto position_of_anchor_relative_to_focus = DOM::position_of_boundary_point_relative_to_other_boundary_point(anchor_node, anchor_offset, focus_node, focus_offset);
|
auto position_of_anchor_relative_to_focus = DOM::position_of_boundary_point_relative_to_other_boundary_point({ anchor_node, anchor_offset }, { focus_node, focus_offset });
|
||||||
if (position_of_anchor_relative_to_focus == DOM::RelativeBoundaryPointPosition::Before) {
|
if (position_of_anchor_relative_to_focus == DOM::RelativeBoundaryPointPosition::Before) {
|
||||||
TRY(new_range->set_start(anchor_node, anchor_offset));
|
TRY(new_range->set_start(anchor_node, anchor_offset));
|
||||||
TRY(new_range->set_end(focus_node, focus_offset));
|
TRY(new_range->set_end(focus_node, focus_offset));
|
||||||
|
@ -414,16 +414,8 @@ bool Selection::contains_node(GC::Ref<DOM::Node> node, bool allow_partial_contai
|
||||||
// start of its range is before or visually equivalent to the first boundary point in the node
|
// start of its range is before or visually equivalent to the first boundary point in the node
|
||||||
// and end of its range is after or visually equivalent to the last boundary point in the node.
|
// and end of its range is after or visually equivalent to the last boundary point in the node.
|
||||||
if (!allow_partial_containment) {
|
if (!allow_partial_containment) {
|
||||||
auto start_relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point(
|
auto start_relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point(m_range->start(), { node, 0 });
|
||||||
*m_range->start_container(),
|
auto end_relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point(m_range->end(), { node, static_cast<WebIDL::UnsignedLong>(node->length()) });
|
||||||
m_range->start_offset(),
|
|
||||||
node,
|
|
||||||
0);
|
|
||||||
auto end_relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point(
|
|
||||||
*m_range->end_container(),
|
|
||||||
m_range->end_offset(),
|
|
||||||
node,
|
|
||||||
node->length());
|
|
||||||
|
|
||||||
return (start_relative_position == DOM::RelativeBoundaryPointPosition::Before || start_relative_position == DOM::RelativeBoundaryPointPosition::Equal)
|
return (start_relative_position == DOM::RelativeBoundaryPointPosition::Before || start_relative_position == DOM::RelativeBoundaryPointPosition::Equal)
|
||||||
&& (end_relative_position == DOM::RelativeBoundaryPointPosition::Equal || end_relative_position == DOM::RelativeBoundaryPointPosition::After);
|
&& (end_relative_position == DOM::RelativeBoundaryPointPosition::Equal || end_relative_position == DOM::RelativeBoundaryPointPosition::After);
|
||||||
|
@ -433,16 +425,8 @@ bool Selection::contains_node(GC::Ref<DOM::Node> node, bool allow_partial_contai
|
||||||
// start of its range is before or visually equivalent to the last boundary point in the node
|
// start of its range is before or visually equivalent to the last boundary point in the node
|
||||||
// and end of its range is after or visually equivalent to the first boundary point in the node.
|
// and end of its range is after or visually equivalent to the first boundary point in the node.
|
||||||
|
|
||||||
auto start_relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point(
|
auto start_relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point(m_range->start(), { node, static_cast<WebIDL::UnsignedLong>(node->length()) });
|
||||||
*m_range->start_container(),
|
auto end_relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point(m_range->end(), { node, 0 });
|
||||||
m_range->start_offset(),
|
|
||||||
node,
|
|
||||||
node->length());
|
|
||||||
auto end_relative_position = DOM::position_of_boundary_point_relative_to_other_boundary_point(
|
|
||||||
*m_range->end_container(),
|
|
||||||
m_range->end_offset(),
|
|
||||||
node,
|
|
||||||
0);
|
|
||||||
|
|
||||||
return (start_relative_position == DOM::RelativeBoundaryPointPosition::Before || start_relative_position == DOM::RelativeBoundaryPointPosition::Equal)
|
return (start_relative_position == DOM::RelativeBoundaryPointPosition::Before || start_relative_position == DOM::RelativeBoundaryPointPosition::Equal)
|
||||||
&& (end_relative_position == DOM::RelativeBoundaryPointPosition::Equal || end_relative_position == DOM::RelativeBoundaryPointPosition::After);
|
&& (end_relative_position == DOM::RelativeBoundaryPointPosition::Equal || end_relative_position == DOM::RelativeBoundaryPointPosition::After);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue