mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-22 09:12:13 -05:00
LibWeb: Implement the "insertHorizontalRule" editing command
This commit is contained in:
parent
c6cde85534
commit
cb05ab6515
Notes:
github-actions[bot]
2025-01-10 22:35:36 +00:00
Author: https://github.com/gmta Commit: https://github.com/LadybirdBrowser/ladybird/commit/cb05ab6515f Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3216
4 changed files with 95 additions and 0 deletions
|
@ -1135,6 +1135,75 @@ bool command_indent_action(DOM::Document& document, String const&)
|
|||
return true;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/editing/docs/execCommand/#the-inserthorizontalrule-command
|
||||
bool command_insert_horizontal_rule_action(DOM::Document& document, String const&)
|
||||
{
|
||||
// 1. Let start node, start offset, end node, and end offset be the active range's start and end nodes and offsets.
|
||||
auto range = active_range(document);
|
||||
auto start = range->start();
|
||||
auto end = range->end();
|
||||
|
||||
// 2. While start offset is 0 and start node's parent is not null, set start offset to start node's index, then set
|
||||
// start node to its parent.
|
||||
while (start.offset == 0 && start.node->parent()) {
|
||||
start.offset = start.node->index();
|
||||
start.node = *start.node->parent();
|
||||
}
|
||||
|
||||
// 3. 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 index, then set end node to its parent.
|
||||
while (end.offset == end.node->length() && end.node->parent()) {
|
||||
end.offset = end.node->index() + 1;
|
||||
end.node = *end.node->parent();
|
||||
}
|
||||
|
||||
// 4. Call collapse(start node, start offset) on the context object's selection.
|
||||
auto& selection = *document.get_selection();
|
||||
MUST(selection.collapse(start.node, start.offset));
|
||||
|
||||
// 5. Call extend(end node, end offset) on the context object's selection.
|
||||
MUST(selection.extend(end.node, end.offset));
|
||||
|
||||
// 6. Delete the selection, with block merging false.
|
||||
delete_the_selection(selection, false);
|
||||
|
||||
// 7. If the active range's start node is neither editable nor an editing host, return true.
|
||||
range = active_range(document);
|
||||
start = range->start();
|
||||
if (!start.node->is_editable_or_editing_host())
|
||||
return true;
|
||||
|
||||
// 8. If the active range's start node is a Text node and its start offset is zero, call collapse() on the context
|
||||
// object's selection, with first argument the active range's start node's parent and second argument the active
|
||||
// range's start node's index.
|
||||
if (is<DOM::Text>(*start.node) && start.offset == 0)
|
||||
MUST(selection.collapse(start.node->parent(), start.node->index()));
|
||||
|
||||
// 9. If the active range's start node is a Text node and its start offset is the length of its start node, call
|
||||
// collapse() on the context object's selection, with first argument the active range's start node's parent, and
|
||||
// the second argument one plus the active range's start node's index.
|
||||
range = active_range(document);
|
||||
start = range->start();
|
||||
if (is<DOM::Text>(*start.node) && start.offset == start.node->length())
|
||||
MUST(selection.collapse(start.node->parent(), start.node->index() + 1));
|
||||
|
||||
// 10. Let hr be the result of calling createElement("hr") on the context object.
|
||||
auto hr = MUST(DOM::create_element(document, HTML::TagNames::hr, Namespace::HTML));
|
||||
|
||||
// 11. Run insertNode(hr) on the active range.
|
||||
MUST(active_range(document)->insert_node(hr));
|
||||
|
||||
// 12. Fix disallowed ancestors of hr.
|
||||
fix_disallowed_ancestors_of_node(hr);
|
||||
|
||||
// 13. Run collapse() on the context object's selection, with first argument hr's parent and the second argument
|
||||
// equal to one plus hr's index.
|
||||
MUST(selection.collapse(hr->parent(), hr->index() + 1));
|
||||
|
||||
// 14. Return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://w3c.github.io/editing/docs/execCommand/#the-insertlinebreak-command
|
||||
bool command_insert_linebreak_action(DOM::Document& document, String const&)
|
||||
{
|
||||
|
@ -1879,6 +1948,12 @@ static Array const commands {
|
|||
.action = command_indent_action,
|
||||
.preserves_overrides = true,
|
||||
},
|
||||
// https://w3c.github.io/editing/docs/execCommand/#the-inserthorizontalrule-command
|
||||
CommandDefinition {
|
||||
.command = CommandNames::insertHorizontalRule,
|
||||
.action = command_insert_horizontal_rule_action,
|
||||
.preserves_overrides = true,
|
||||
},
|
||||
// https://w3c.github.io/editing/docs/execCommand/#the-insertlinebreak-command
|
||||
CommandDefinition {
|
||||
.command = CommandNames::insertLineBreak,
|
||||
|
|
|
@ -44,6 +44,7 @@ bool command_format_block_indeterminate(DOM::Document const&);
|
|||
String command_format_block_value(DOM::Document const&);
|
||||
bool command_forward_delete_action(DOM::Document&, String const&);
|
||||
bool command_indent_action(DOM::Document&, String const&);
|
||||
bool command_insert_horizontal_rule_action(DOM::Document&, String const&);
|
||||
bool command_insert_linebreak_action(DOM::Document&, String const&);
|
||||
bool command_insert_paragraph_action(DOM::Document&, String const&);
|
||||
bool command_italic_action(DOM::Document&, String const&);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
foo<hr>bar
|
|
@ -0,0 +1,18 @@
|
|||
<script src="../include.js"></script>
|
||||
<div contenteditable="true">foobar</div>
|
||||
<script>
|
||||
test(() => {
|
||||
var divElm = document.querySelector('div');
|
||||
|
||||
// Put cursor between 'foo' and 'bar'
|
||||
var range = document.createRange();
|
||||
getSelection().addRange(range);
|
||||
range.setStart(divElm.childNodes[0], 3);
|
||||
range.setEnd(divElm.childNodes[0], 3);
|
||||
|
||||
// Insert horizontal rule
|
||||
document.execCommand('insertHorizontalRule');
|
||||
|
||||
println(divElm.innerHTML);
|
||||
});
|
||||
</script>
|
Loading…
Reference in a new issue