mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 09:39:39 +00:00
LibWeb: Implement the "insertImage" editing command
This commit is contained in:
parent
20fb7b1a49
commit
01ce9cb151
Notes:
github-actions[bot]
2025-01-10 22:35:23 +00:00
Author: https://github.com/gmta
Commit: 01ce9cb151
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3216
4 changed files with 71 additions and 0 deletions
|
@ -1276,6 +1276,51 @@ bool command_insert_html_action(DOM::Document& document, String const& value)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://w3c.github.io/editing/docs/execCommand/#the-insertimage-command
|
||||||
|
bool command_insert_image_action(DOM::Document& document, String const& value)
|
||||||
|
{
|
||||||
|
// 1. If value is the empty string, return false.
|
||||||
|
if (value.is_empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 2. Delete the selection, with strip wrappers false.
|
||||||
|
auto& selection = *document.get_selection();
|
||||||
|
delete_the_selection(selection, true, false);
|
||||||
|
|
||||||
|
// 3. Let range be the active range.
|
||||||
|
auto range = active_range(document);
|
||||||
|
|
||||||
|
// 4. If the active range's start node is neither editable nor an editing host, return true.
|
||||||
|
if (!range->start_container()->is_editable_or_editing_host())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 5. If range's start node is a block node whose sole child is a br, and its start offset is 0, remove its start
|
||||||
|
// node's child from it.
|
||||||
|
auto start_node = range->start_container();
|
||||||
|
if (is_block_node(start_node) && start_node->child_count() == 1 && is<HTML::HTMLBRElement>(*start_node->first_child())
|
||||||
|
&& range->start_offset() == 0)
|
||||||
|
start_node->first_child()->remove();
|
||||||
|
|
||||||
|
// 6. Let img be the result of calling createElement("img") on the context object.
|
||||||
|
auto img = MUST(DOM::create_element(document, HTML::TagNames::img, Namespace::HTML));
|
||||||
|
|
||||||
|
// 7. Run setAttribute("src", value) on img.
|
||||||
|
MUST(img->set_attribute(HTML::AttributeNames::src, value));
|
||||||
|
|
||||||
|
// 8. Run insertNode(img) on range.
|
||||||
|
MUST(range->insert_node(img));
|
||||||
|
|
||||||
|
// 9. Let selection be the result of calling getSelection() on the context object.
|
||||||
|
// NOTE: Already done so in step 2.
|
||||||
|
|
||||||
|
// 10. Run collapse() on selection, with first argument equal to the parent of img and the second argument equal to
|
||||||
|
// one plus the index of img.
|
||||||
|
MUST(selection.collapse(img->parent(), img->index() + 1));
|
||||||
|
|
||||||
|
// 11. Return true.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#the-insertlinebreak-command
|
// https://w3c.github.io/editing/docs/execCommand/#the-insertlinebreak-command
|
||||||
bool command_insert_linebreak_action(DOM::Document& document, String const&)
|
bool command_insert_linebreak_action(DOM::Document& document, String const&)
|
||||||
{
|
{
|
||||||
|
@ -2032,6 +2077,12 @@ static Array const commands {
|
||||||
.action = command_insert_html_action,
|
.action = command_insert_html_action,
|
||||||
.preserves_overrides = true,
|
.preserves_overrides = true,
|
||||||
},
|
},
|
||||||
|
// https://w3c.github.io/editing/docs/execCommand/#the-insertimage-command
|
||||||
|
CommandDefinition {
|
||||||
|
.command = CommandNames::insertImage,
|
||||||
|
.action = command_insert_image_action,
|
||||||
|
.preserves_overrides = true,
|
||||||
|
},
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#the-insertlinebreak-command
|
// https://w3c.github.io/editing/docs/execCommand/#the-insertlinebreak-command
|
||||||
CommandDefinition {
|
CommandDefinition {
|
||||||
.command = CommandNames::insertLineBreak,
|
.command = CommandNames::insertLineBreak,
|
||||||
|
|
|
@ -46,6 +46,7 @@ bool command_forward_delete_action(DOM::Document&, String const&);
|
||||||
bool command_indent_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_horizontal_rule_action(DOM::Document&, String const&);
|
||||||
bool command_insert_html_action(DOM::Document&, String const&);
|
bool command_insert_html_action(DOM::Document&, String const&);
|
||||||
|
bool command_insert_image_action(DOM::Document&, String const&);
|
||||||
bool command_insert_linebreak_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_insert_paragraph_action(DOM::Document&, String const&);
|
||||||
bool command_italic_action(DOM::Document&, String const&);
|
bool command_italic_action(DOM::Document&, String const&);
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
foo<img src="../../../Assets/120.png">bar
|
18
Tests/LibWeb/Text/input/Editing/execCommand-insertImage.html
Normal file
18
Tests/LibWeb/Text/input/Editing/execCommand-insertImage.html
Normal file
|
@ -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 HTML
|
||||||
|
document.execCommand('insertImage', false, '../../../Assets/120.png');
|
||||||
|
|
||||||
|
println(divElm.innerHTML);
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue