mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-28 11:49:44 +00:00
LibWeb: Do not rely on the layout tree for collapsed line breaks
The editing command that relies the most on this, `insertLinebreak`, did not perform a layout update after inserting a `<br>` which caused this algorithm to always return false. But instead of actually building the layout tree needlessly, we can check the DOM tree instead.
This commit is contained in:
parent
71a4e18bf8
commit
295b78f7d3
Notes:
github-actions[bot]
2025-05-01 12:45:22 +00:00
Author: https://github.com/gmta
Commit: 295b78f7d3
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4542
3 changed files with 17 additions and 9 deletions
|
@ -1981,15 +1981,10 @@ bool is_collapsed_line_break(GC::Ref<DOM::Node> node)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// that begins a line box which has nothing else in it, and therefore has zero height.
|
// that begins a line box which has nothing else in it, and therefore has zero height.
|
||||||
auto layout_node = node->layout_node();
|
// NOTE: We check this on the DOM-level by seeing if the next node is neither a non-empty text node nor a <br>.
|
||||||
if (!layout_node)
|
if (auto text_node = as_if<DOM::Text>(node->next_sibling()))
|
||||||
return false;
|
return text_node->text_content().value_or({}).is_empty();
|
||||||
VERIFY(is<Layout::BreakNode>(*layout_node));
|
return !is<HTML::HTMLBRElement>(node->next_sibling());
|
||||||
|
|
||||||
// NOTE: We do not generate a TextNode for empty text after the break, so if we do not have a sibling or if that
|
|
||||||
// sibling is not a TextNode, we consider it a collapsed line break.
|
|
||||||
auto* next_layout_node = layout_node->next_sibling();
|
|
||||||
return !is<Layout::TextNode>(next_layout_node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/editing/docs/execCommand/#collapsed-whitespace-node
|
// https://w3c.github.io/editing/docs/execCommand/#collapsed-whitespace-node
|
||||||
|
|
|
@ -7,3 +7,5 @@ Before: "<p style="white-space: pre">foobar</p>"
|
||||||
After: "<p style="white-space: pre">foobar
|
After: "<p style="white-space: pre">foobar
|
||||||
|
|
||||||
</p>"
|
</p>"
|
||||||
|
Before: "foo"
|
||||||
|
After: "foo<br><br>"
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
<div id="a" contenteditable>foobar</div>
|
<div id="a" contenteditable>foobar</div>
|
||||||
<div id="b" contenteditable><p style="white-space: pre">foobar</p></div>
|
<div id="b" contenteditable><p style="white-space: pre">foobar</p></div>
|
||||||
<div id="c" contenteditable><p style="white-space: pre">foobar</p></div>
|
<div id="c" contenteditable><p style="white-space: pre">foobar</p></div>
|
||||||
|
<div id="d" contenteditable>foo</div>
|
||||||
<script>
|
<script>
|
||||||
test(() => {
|
test(() => {
|
||||||
let divA = document.querySelector('div#a');
|
let divA = document.querySelector('div#a');
|
||||||
let divB = document.querySelector('div#b');
|
let divB = document.querySelector('div#b');
|
||||||
let divC = document.querySelector('div#c');
|
let divC = document.querySelector('div#c');
|
||||||
|
let divD = document.querySelector('div#d');
|
||||||
|
|
||||||
document.body.offsetWidth // Force a layout
|
document.body.offsetWidth // Force a layout
|
||||||
|
|
||||||
|
@ -37,5 +39,14 @@
|
||||||
document.execCommand('insertLinebreak');
|
document.execCommand('insertLinebreak');
|
||||||
println(`After: "${divC.innerHTML}"`);
|
println(`After: "${divC.innerHTML}"`);
|
||||||
getSelection().empty();
|
getSelection().empty();
|
||||||
|
|
||||||
|
// D: Insert linebreak after 'foo'
|
||||||
|
println(`Before: "${divD.innerHTML}"`);
|
||||||
|
var range = document.createRange();
|
||||||
|
range.setStart(divD.firstChild, 3);
|
||||||
|
getSelection().addRange(range);
|
||||||
|
document.execCommand('insertLinebreak');
|
||||||
|
println(`After: "${divD.innerHTML}"`);
|
||||||
|
getSelection().empty();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue