655 Commits

Author SHA1 Message Date
Masayuki Nakano
8e53bd4fcd Bug 1968820 - Make HTMLEditor::InsertPaddingBRElementIfNeeded() put <br> before the mail-quote a=dmeehan
When we find a block boundary, it may be current block's boundary or
other block's boundary.  The lambda assume only the former, but the
STR of this bug hits the latter case.

So, when user modifies the text before a mail-quote which is a block of
`<span>` element should put `<br>` before it rather than end of it.

Differential Revision: https://phabricator.services.mozilla.com/D270782
2025-10-31 12:51:58 +00:00
Masayuki Nakano
f3c6a960d9 Bug 1968843 - Make HTMLEditor::HandleInsertText() manage Selection if committing composition a=dmeehan DONTBUILD
When committing composition string,
`WhiteSpaceVisibilityKeeper::InsertOrUpdateCompositionString()` may
replace commit string with normalized white-spaces.  Therefore, if
the last character is a white-space, it may be replaced with the other
white-space (ASCII white-space vs. NBSP).  Then, `Selection` collapsed
after the last character will be moved to start of the replaced
white-spaces.  So, when committing composition,
`HTMLEditor::HandleInsertText()` may need to change `Selection` by
itself.

Original Revision: https://phabricator.services.mozilla.com/D252278

Differential Revision: https://phabricator.services.mozilla.com/D253280
2025-06-11 17:05:48 +00:00
Masayuki Nakano
487ff798cd Bug 1964011 - part 3: Make operator<< overload for EditorDOMPointeBase export a few characters of container iif the container is a Text r=m_kato
This helps to distinguish which the instance points a `Text`.

Depends on D248369

Differential Revision: https://phabricator.services.mozilla.com/D248370
2025-05-09 06:49:32 +00:00
Masayuki Nakano
8dd9d35fa1 Bug 1964011 - part 2: Make the editor classes log text input r=m_kato
Depends on D248368

Differential Revision: https://phabricator.services.mozilla.com/D248369
2025-05-09 06:49:28 +00:00
Masayuki Nakano
fb1d603cfd Bug 1961521 - Make HTMLEditor::HandleInsertText() collapse Selection properly after deleting composition r=m_kato
When inserting text or deleting text is for updating composition string,
`InsertTextWithTransaction()` does not suggest caret position because in the
most cases, `CompositionTransaction` updating `Selection` properly.  However,
if it's deleting existing composition (i.e., replacing the composition with
empty string), `HTMLEditor::HandleInsertText()` doesn't use
`CompositionTransaction` to update composition.  Instead, it uses the suggested
caret position from `InsertTextWithTransaction()` even though it's always unset.
Therefore, if the composition string follows some collapsible white-spaces and
they are replaced, `Selection` is automatically moved to the start position of
the replaced range and `HTMLEditor::HandleInsertText()` does not maintain the
caret position.

Therefore, this patch make it collapse `Selection` to end of the inserted text
where the composition string was.

Differential Revision: https://phabricator.services.mozilla.com/D246087
2025-04-21 23:49:31 +00:00
Masayuki Nakano
b2e66c86f6 Bug 1940377 - part 8: Make HTMLEditor stop normalizing white-spaces during initialization r=m_kato
Enabling the new normalizer causes this assertion failure:
```
###!!! ASSERTION: Want to fire DOMNodeRemoved event, but it's not safe: 'Error', file /builds/worker/checkouts/gecko/dom/base/nsContentUtils.cpp:5586
#01: NS_DebugBreak [xpcom/base/nsDebugImpl.cpp:508]
#02: nsContentUtils::MaybeFireNodeRemoved(nsINode*, nsINode*) [dom/base/nsContentUtils.cpp:5587]
#03: nsINode::RemoveChild(nsINode&, mozilla::ErrorResult&) [dom/base/nsINode.cpp:0]
#04: mozilla::DeleteNodeTransaction::DoTransaction() [editor/libeditor/DeleteNodeTransaction.cpp:112]
#05: mozilla::EditorBase::DoTransactionInternal(nsITransaction*) [editor/libeditor/EditorBase.cpp:929]
#06: mozilla::EditorBase::DeleteNodeWithTransaction(nsIContent&) [editor/libeditor/EditorBase.cpp:2685]
#07: mozilla::WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(mozilla::HTMLEditor&, mozilla::EditorDOMPointBase<RefPtr<mozilla::dom::Text>, nsIContent*> const&, mozilla::EnumSet<mozilla::WhiteSpaceVisibilityKeeper::NormalizeOption, unsigned int>) [editor/libeditor/WhiteSpaceVisibilityKeeper.cpp:1384]
#08: mozilla::WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(mozilla::HTMLEditor&, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&, mozilla::EnumSet<mozilla::WhiteSpaceVisibilityKeeper::NormalizeOption, unsigned int>) [editor/libeditor/WhiteSpaceVisibilityKeeper.cpp:1599]
#09: mozilla::HTMLEditor::PrepareToInsertLineBreak(mozilla::HTMLEditor::LineBreakType, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) [editor/libeditor/HTMLEditor.cpp:4418]
#10: mozilla::EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) [editor/libeditor/EditorBase.cpp:2511]
#11: mozilla::HTMLEditor::InsertBRElementToEmptyListItemsAndTableCellsInRange(mozilla::RangeBoundaryBase<nsINode*, nsIContent*> const&, mozilla::RangeBoundaryBase<nsINode*, nsIContent*> const&) [editor/libeditor/HTMLEditSubActionHandler.cpp:0]
#12: mozilla::HTMLEditor::InitEditorContentAndSelection() [editor/libeditor/HTMLEditSubActionHandler.cpp:187]
#13: mozilla::HTMLEditor::Init(mozilla::dom::Document&, mozilla::ComposerCommandsUpdater&, unsigned int) [editor/libeditor/HTMLEditor.cpp:412]
#14: nsEditingSession::SetupEditorOnWindow(nsPIDOMWindowOuter&) [editor/composer/nsEditingSession.cpp:405]
```

The initialization is required only for empty table cells and empty list items
and they are typically not used at initial document.  So, I think that it's fine
to stop normalizing white-spaces before succeeded to initialize `HTMLEditor`.

If this change causes a web-compat issue in the wild, let's make it run
asynchronously.

Differential Revision: https://phabricator.services.mozilla.com/D239473
2025-03-08 22:31:57 +00:00
Masayuki Nakano
dc6fec20e3 Bug 1940377 - part 7: Make HTMLEditor normalize surrounding white-spaces of commit string r=m_kato
For avoiding invisible white-space issues around composition string and for
avoiding making `CompositionTransaction` confused, we normalize white-spaces
around composition string boundaries with using NBSPs more than usual.
Therefore, we need to recover them as usual when ending the composition.

Differential Revision: https://phabricator.services.mozilla.com/D239469
2025-03-08 22:31:57 +00:00
Masayuki Nakano
2e3d9fe6d5 Bug 1940377 - part 6: Make delete handlers use the new white-space normalizer r=m_kato
Unfortunately, this patch becomes big because this includes multiple utility
methods to normalize white-spaces and touching a lot of places.

In some edge cases, this starts failing when the new white-space normalizer is
enabled.

```
FAIL execCommand("forwarddelete", false, ""): "a &nbsp;[] |&nbsp; &nbsp;b" - assert_equals: Modified text is wrong expected "a &nbsp;" but got "a&nbsp;&nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;b" - assert_equals: Modified text is wrong expected "a&nbsp;&nbsp;&nbsp;" but got "a&nbsp; &nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]b|&nbsp;&nbsp;&nbsp;&nbsp;c" - assert_equals: Modified text is wrong expected "a&nbsp;&nbsp;&nbsp;" but got "a&nbsp; &nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]&nbsp;<span style=white-space:pre;>   </span>" - assert_equals: expected "a&nbsp;&nbsp;&nbsp;<span style=\"white-space:pre;\">   </span>" but got "a&nbsp; &nbsp;<span style=\"white-space:pre;\">   </span>"
```
In these failures, we normalize the trailing white-spaces of the preceding
`Text` too, but Chrome does not do that.  However, in some cases, they do
in similar cases.  Therefore, it's hard to align all cases due to the handling
order difference.  Additionally, these failure results are not odd.  So, these
new failures are acceptable.

```
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp;<span> &nbsp;def</span></span>" - assert_equals: expected "<span>abc<span>&nbsp; def</span></span>" but got "<span>abc<span> &nbsp;def</span></span>"
FAIL execCommand("forwarddelete", false, ""): "<span><span>abc[]&nbsp;</span> &nbsp;def</span>" - assert_equals: expected "<span><span>abc</span>&nbsp; def</span>" but got "<span><span>abc</span> &nbsp;def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp;</span><span> &nbsp;def</span>" - assert_equals: expected "<span>abc</span><span>&nbsp; def</span>" but got "<span>abc</span><span> &nbsp;def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp; </span><span>&nbsp;&nbsp;def</span>" - assert_equals: expected "<span>abc&nbsp;</span><span>&nbsp;&nbsp;def</span>" but got "<span>abc </span><span>&nbsp;&nbsp;def</span>"

```
In these failures, we don't normalize the leading white-spaces of the following
`Text`.  However, Chrome does so in some other cases.  So, it's hard to align
the behavior in these cases too.  The new normalizer ensures that the preceding
`Text` ends with a visible char.  Therefore, the following `Text` won't starts
with new invisible white-spaces.  Therefore, these failures are also acceptable.

```
FAIL execCommand("forwarddelete", false, ""): "<span style=white-space:pre;>  [] </span>&nbsp;&nbsp;&nbsp;a" - assert_equals: expected "<span style=\"white-space:pre;\">  </span>&nbsp; &nbsp;a" but got "<span style=\"white-space:pre;\">  </span>&nbsp;&nbsp;&nbsp;a"
```
In this failure, we don't normalize the following `Text` but Chrome does it.
However, I don't think we should do it because this updates the `Text` which
is preformatted.  Therefore, this is also acceptable.

So, I think that we can accept all new failures.

Differential Revision: https://phabricator.services.mozilla.com/D239468
2025-03-08 22:31:56 +00:00
Masayuki Nakano
a4270d20ef Bug 1940377 - part 4: Make HTMLEditor normalize white-spaces before inserting HTML fragment if the new normalizer is enabled r=m_kato
Unfortunately, this change does not make
`white-spaces-after-insert-image.tentative.html?paste-image` pass because we
paste the `<div>` at pasting the `<img>`, but Chrome pastes only the `<img>`.

Differential Revision: https://phabricator.services.mozilla.com/D239466
2025-03-08 22:31:55 +00:00
Masayuki Nakano
e8e8d245bc Bug 1940377 - part 3: Make "insert paragraph" handlers use the new normalizer if it's enabled r=m_kato
Unfortunately, this change does not make
`white-spaces-after-execCommand-insertparagraph.tentative.html` pass because
the insert paragraph handler inserts a temporary `<br>` element and that causes
normalizing the following white-spaces at the split point.  However, Chrome
does not normalize the following white-spaces if it begins with an NBSP.

Differential Revision: https://phabricator.services.mozilla.com/D239465
2025-03-08 22:31:55 +00:00
Masayuki Nakano
5d714df94f Bug 1940377 - part 2: Make HandleInsertLineBreak use the new normalizer if it's available r=m_kato
When inserting a `<br>` element or a preformatted line break at middle of a
`Text`, we need to split it first.  At this time, we should normalize the
surrounding white-spaces before split.  Then, we can use only one
`ReplaceTextTransaction` instance for the normalization in the most cases.

Differential Revision: https://phabricator.services.mozilla.com/D239464
2025-03-08 22:31:54 +00:00
Masayuki Nakano
c0723c81ee Bug 1940377 - part 1: Make WhiteSpaceVisibilityKeeper::InsertTextOrInsertOrUpdateCompositionString support blink compatible white-space sequence r=m_kato
First, it makes it deletes invisible white-spaces at the insertion point.
This makes the further processing simpler.

Second, it extends the range to update in `Text` which will contain the
insertion string when it's not used for inserting nor updating composition
string, as containing all surrounding white-spaces at the insertion point.

Next, it normalizes the inserting string with the surrounding white-spaces with
the same rules as the other browsers especially as Chrome.
1. a collapsible white-space at start or end of a `Text` is always an NBSP.
2. a collapsible white-space immediately before or after a preformatted line
break is always an NBSP.
3. a collapsible white-space surrounded by non-collapsible chars is always an
ASCII white-space.
4. collapsible white-spaces are pairs of an NBSP and an ASCII white-space.

Then, we can make `HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal()`
stop normalizing white-spaces when inserting text.

Differential Revision: https://phabricator.services.mozilla.com/D239463
2025-03-08 22:31:54 +00:00
Goloman Adrian
2973813822 Backed out 9 changesets (bug 1940377) for causing wpt failures @elete-to-join-blocks.tentative.html.
Backed out changeset c08fbe668983 (bug 1940377)
Backed out changeset afe170b7d586 (bug 1940377)
Backed out changeset fbd25039fe81 (bug 1940377)
Backed out changeset 9cec5876c849 (bug 1940377)
Backed out changeset d4eabf000418 (bug 1940377)
Backed out changeset d6b44f519481 (bug 1940377)
Backed out changeset a3fd780478a3 (bug 1940377)
Backed out changeset 80dba0103823 (bug 1940377)
Backed out changeset d06e8bb673e8 (bug 1940377)
2025-03-08 08:25:13 +02:00
Masayuki Nakano
521972f410 Bug 1940377 - part 8: Make HTMLEditor stop normalizing white-spaces during initialization r=m_kato
Enabling the new normalizer causes this assertion failure:
```
###!!! ASSERTION: Want to fire DOMNodeRemoved event, but it's not safe: 'Error', file /builds/worker/checkouts/gecko/dom/base/nsContentUtils.cpp:5586
#01: NS_DebugBreak [xpcom/base/nsDebugImpl.cpp:508]
#02: nsContentUtils::MaybeFireNodeRemoved(nsINode*, nsINode*) [dom/base/nsContentUtils.cpp:5587]
#03: nsINode::RemoveChild(nsINode&, mozilla::ErrorResult&) [dom/base/nsINode.cpp:0]
#04: mozilla::DeleteNodeTransaction::DoTransaction() [editor/libeditor/DeleteNodeTransaction.cpp:112]
#05: mozilla::EditorBase::DoTransactionInternal(nsITransaction*) [editor/libeditor/EditorBase.cpp:929]
#06: mozilla::EditorBase::DeleteNodeWithTransaction(nsIContent&) [editor/libeditor/EditorBase.cpp:2685]
#07: mozilla::WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitTextNodeAt(mozilla::HTMLEditor&, mozilla::EditorDOMPointBase<RefPtr<mozilla::dom::Text>, nsIContent*> const&, mozilla::EnumSet<mozilla::WhiteSpaceVisibilityKeeper::NormalizeOption, unsigned int>) [editor/libeditor/WhiteSpaceVisibilityKeeper.cpp:1384]
#08: mozilla::WhiteSpaceVisibilityKeeper::NormalizeWhiteSpacesToSplitAt(mozilla::HTMLEditor&, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&, mozilla::EnumSet<mozilla::WhiteSpaceVisibilityKeeper::NormalizeOption, unsigned int>) [editor/libeditor/WhiteSpaceVisibilityKeeper.cpp:1599]
#09: mozilla::HTMLEditor::PrepareToInsertLineBreak(mozilla::HTMLEditor::LineBreakType, mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) [editor/libeditor/HTMLEditor.cpp:4418]
#10: mozilla::EditorBase::InsertPaddingBRElementForEmptyLastLineWithTransaction(mozilla::EditorDOMPointBase<nsCOMPtr<nsINode>, nsCOMPtr<nsIContent> > const&) [editor/libeditor/EditorBase.cpp:2511]
#11: mozilla::HTMLEditor::InsertBRElementToEmptyListItemsAndTableCellsInRange(mozilla::RangeBoundaryBase<nsINode*, nsIContent*> const&, mozilla::RangeBoundaryBase<nsINode*, nsIContent*> const&) [editor/libeditor/HTMLEditSubActionHandler.cpp:0]
#12: mozilla::HTMLEditor::InitEditorContentAndSelection() [editor/libeditor/HTMLEditSubActionHandler.cpp:187]
#13: mozilla::HTMLEditor::Init(mozilla::dom::Document&, mozilla::ComposerCommandsUpdater&, unsigned int) [editor/libeditor/HTMLEditor.cpp:412]
#14: nsEditingSession::SetupEditorOnWindow(nsPIDOMWindowOuter&) [editor/composer/nsEditingSession.cpp:405]
```

The initialization is required only for empty table cells and empty list items
and they are typically not used at initial document.  So, I think that it's fine
to stop normalizing white-spaces before succeeded to initialize `HTMLEditor`.

If this change causes a web-compat issue in the wild, let's make it run
asynchronously.

Differential Revision: https://phabricator.services.mozilla.com/D239473
2025-03-08 00:23:17 +00:00
Masayuki Nakano
e04dcc4edc Bug 1940377 - part 7: Make HTMLEditor normalize surrounding white-spaces of commit string r=m_kato
For avoiding invisible white-space issues around composition string and for
avoiding making `CompositionTransaction` confused, we normalize white-spaces
around composition string boundaries with using NBSPs more than usual.
Therefore, we need to recover them as usual when ending the composition.

Differential Revision: https://phabricator.services.mozilla.com/D239469
2025-03-08 00:23:17 +00:00
Masayuki Nakano
f8da424b74 Bug 1940377 - part 6: Make delete handlers use the new white-space normalizer r=m_kato
Unfortunately, this patch becomes big because this includes multiple utility
methods to normalize white-spaces and touching a lot of places.

In some edge cases, this starts failing when the new white-space normalizer is
enabled.

```
FAIL execCommand("forwarddelete", false, ""): "a &nbsp;[] |&nbsp; &nbsp;b" - assert_equals: Modified text is wrong expected "a &nbsp;" but got "a&nbsp;&nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;b" - assert_equals: Modified text is wrong expected "a&nbsp;&nbsp;&nbsp;" but got "a&nbsp; &nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]b|&nbsp;&nbsp;&nbsp;&nbsp;c" - assert_equals: Modified text is wrong expected "a&nbsp;&nbsp;&nbsp;" but got "a&nbsp; &nbsp;"
FAIL execCommand("forwarddelete", false, ""): "a&nbsp;&nbsp;&nbsp;[]&nbsp;<span style=white-space:pre;>   </span>" - assert_equals: expected "a&nbsp;&nbsp;&nbsp;<span style=\"white-space:pre;\">   </span>" but got "a&nbsp; &nbsp;<span style=\"white-space:pre;\">   </span>"
```
In these failures, we normalize the trailing white-spaces of the preceding
`Text` too, but Chrome does not do that.  However, in some cases, they do
in similar cases.  Therefore, it's hard to align all cases due to the handling
order difference.  Additionally, these failure results are not odd.  So, these
new failures are acceptable.

```
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp;<span> &nbsp;def</span></span>" - assert_equals: expected "<span>abc<span>&nbsp; def</span></span>" but got "<span>abc<span> &nbsp;def</span></span>"
FAIL execCommand("forwarddelete", false, ""): "<span><span>abc[]&nbsp;</span> &nbsp;def</span>" - assert_equals: expected "<span><span>abc</span>&nbsp; def</span>" but got "<span><span>abc</span> &nbsp;def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp;</span><span> &nbsp;def</span>" - assert_equals: expected "<span>abc</span><span>&nbsp; def</span>" but got "<span>abc</span><span> &nbsp;def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[]&nbsp; </span><span>&nbsp;&nbsp;def</span>" - assert_equals: expected "<span>abc&nbsp;</span><span>&nbsp;&nbsp;def</span>" but got "<span>abc </span><span>&nbsp;&nbsp;def</span>"

```
In these failures, we don't normalize the leading white-spaces of the following
`Text`.  However, Chrome does so in some other cases.  So, it's hard to align
the behavior in these cases too.  The new normalizer ensures that the preceding
`Text` ends with a visible char.  Therefore, the following `Text` won't starts
with new invisible white-spaces.  Therefore, these failures are also acceptable.

```
FAIL execCommand("forwarddelete", false, ""): "<span style=white-space:pre;>  [] </span>&nbsp;&nbsp;&nbsp;a" - assert_equals: expected "<span style=\"white-space:pre;\">  </span>&nbsp; &nbsp;a" but got "<span style=\"white-space:pre;\">  </span>&nbsp;&nbsp;&nbsp;a"
```
In this failure, we don't normalize the following `Text` but Chrome does it.
However, I don't think we should do it because this updates the `Text` which
is preformatted.  Therefore, this is also acceptable.

So, I think that we can accept all new failures.

Differential Revision: https://phabricator.services.mozilla.com/D239468
2025-03-08 00:23:16 +00:00
Masayuki Nakano
52d313f25e Bug 1940377 - part 4: Make HTMLEditor normalize white-spaces before inserting HTML fragment if the new normalizer is enabled r=m_kato
Unfortunately, this change does not make
`white-spaces-after-insert-image.tentative.html?paste-image` pass because we
paste the `<div>` at pasting the `<img>`, but Chrome pastes only the `<img>`.

Differential Revision: https://phabricator.services.mozilla.com/D239466
2025-03-08 00:23:15 +00:00
Masayuki Nakano
e14afee1c1 Bug 1940377 - part 3: Make "insert paragraph" handlers use the new normalizer if it's enabled r=m_kato
Unfortunately, this change does not make
`white-spaces-after-execCommand-insertparagraph.tentative.html` pass because
the insert paragraph handler inserts a temporary `<br>` element and that causes
normalizing the following white-spaces at the split point.  However, Chrome
does not normalize the following white-spaces if it begins with an NBSP.

Differential Revision: https://phabricator.services.mozilla.com/D239465
2025-03-08 00:23:15 +00:00
Masayuki Nakano
cb5f775b5c Bug 1940377 - part 2: Make HandleInsertLineBreak use the new normalizer if it's available r=m_kato
When inserting a `<br>` element or a preformatted line break at middle of a
`Text`, we need to split it first.  At this time, we should normalize the
surrounding white-spaces before split.  Then, we can use only one
`ReplaceTextTransaction` instance for the normalization in the most cases.

Differential Revision: https://phabricator.services.mozilla.com/D239464
2025-03-08 00:23:15 +00:00
Masayuki Nakano
f7f5dd6a64 Bug 1940377 - part 1: Make WhiteSpaceVisibilityKeeper::InsertTextOrInsertOrUpdateCompositionString support blink compatible white-space sequence r=m_kato
First, it makes it deletes invisible white-spaces at the insertion point.
This makes the further processing simpler.

Second, it extends the range to update in `Text` which will contain the
insertion string when it's not used for inserting nor updating composition
string, as containing all surrounding white-spaces at the insertion point.

Next, it normalizes the inserting string with the surrounding white-spaces with
the same rules as the other browsers especially as Chrome.
1. a collapsible white-space at start or end of a `Text` is always an NBSP.
2. a collapsible white-space immediately before or after a preformatted line
break is always an NBSP.
3. a collapsible white-space surrounded by non-collapsible chars is always an
ASCII white-space.
4. collapsible white-spaces are pairs of an NBSP and an ASCII white-space.

Then, we can make `HTMLEditor::OnEndHandlingTopLevelEditSubActionInternal()`
stop normalizing white-spaces when inserting text.

Differential Revision: https://phabricator.services.mozilla.com/D239463
2025-03-08 00:23:14 +00:00
Masayuki Nakano
8bb457917b Bug 1949364 - Make EditorBase::HandleInsertText take further information of composition state r=m_kato
In bug 1940377, `HandleInsertText` will need to normalize surrounding
white-spaces after updating composition string at composition end.  To consider
it easier, it's nicer that it takes more detail for the purpose of inserting
text.

Differential Revision: https://phabricator.services.mozilla.com/D239077
2025-02-26 05:56:24 +00:00
Masayuki Nakano
de4057edf4 Bug 1948172 - Use editable point when suggesting caret point r=m_kato
If I run `./mach wpt testing/web-platform/tests/editing` with just enabling the
new normalizer, I see some assertion failures which are caused by scanning or
updating non-editable regions.

According to the debug result, it's caused by sometimes caret point is suggested
in non-editable node and further handling will use various utilities which
asserts whether the target is editable.

Ideally, we should add assertion into `CaretPoint`, but it's hard and I don't
have enough time to fix every regression which will be found by fuzzing tests
even though most of them are not so important in the real web apps.  Therefore,
this fixes only the causes which I found in the WPTs.

Differential Revision: https://phabricator.services.mozilla.com/D238408
2025-02-20 02:08:33 +00:00
Masayuki Nakano
6b49882e22 Bug 1947107 - Rename WhiteSpaceVisibilityKeeper::ReplaceText r=m_kato
Despite the name, it does not replace text of the specified the range.

The range is not collapsed only when updating composition string and even in
the case, `EditorBase::InsertTextWithTransaction` automatically creates
a `CompositionTransaction` and the transaction will delete the existing
composition string before inserting the new string.

For making the job of the method clearer, this patch renames it as
`InsertOrUpdateCompositionString` and it's actually implemented by
`InsertTextOrInsertOrUpdateCompositionString`.

Differential Revision: https://phabricator.services.mozilla.com/D237525
2025-02-13 04:29:46 +00:00
Masayuki Nakano
ad9fbd6b1a Bug 1947099 - Get rid of unused aDocument parameter of EditorBase::InsertTextWithTransaction r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D237518
2025-02-11 23:42:53 +00:00
Masayuki Nakano
da4abce2d9 Bug 1945714 - Rename RangeBoundaryBase::Container() to GetContainer() r=jjaschke,dom-core
Usually, we name methods as `GetFoo()` if they may return `nullptr`, on the
other hand, we name methods as `Foo()` if they won't return `nullptr`.

`RangeBoundaryBase::Container()` may return `nullptr`.  So, this name may cause
misleading of some developers.  Let's rename it as `GetContainer()`.

This does not change anything for avoiding merge conflict with the other
landings.

Differential Revision: https://phabricator.services.mozilla.com/D236796
2025-02-10 01:29:40 +00:00
Masayuki Nakano
b67e405f29 Bug 1926483 - part 4: Make WSRunScanner::Scan(InclusiveNext|Previous)VisibleNodeOrBlockBoundary take WSRunScanner::Scan and ancestor limiter r=m_kato
Note that this removes a lot of `aEditingHost` params.  This may cause odd
behavior if editing host is changed by a legacy mutation event listener.
However, it'll be completely deleted soon and even if we meet some regressions,
we can just restore the param to set `aAncestorLimiter`.

Differential Revision: https://phabricator.services.mozilla.com/D233794
2025-01-24 05:00:48 +00:00
Masayuki Nakano
d6f4a828d7 Bug 1926483 - part 2: Make WSRunScanner::Get(InclusiveNext|Previous)CharPoint free from editing host r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D233792
2025-01-24 05:00:47 +00:00
Masayuki Nakano
395226db0c Bug 1926483 - part 1: Make WSRunScanner instance free from editing host r=m_kato
If it scans starting from a editable point, it does not require the editing
host as an ancestor limiter.  Therefore, some users can be free from editing
host.

Differential Revision: https://phabricator.services.mozilla.com/D233791
2025-01-24 05:00:47 +00:00
Butkovits Atila
173aee505b Backed out 5 changesets (bug 1926483) for causing failures at WSRunScanner.h. CLOSED TREE
Backed out changeset fa4c36cef1c5 (bug 1926483)
Backed out changeset 24bdcd7af3e0 (bug 1926483)
Backed out changeset 1df51ca968f8 (bug 1926483)
Backed out changeset 7aceecb585e4 (bug 1926483)
Backed out changeset 41b040b374a2 (bug 1926483)
2025-01-23 07:35:22 +02:00
Masayuki Nakano
8e2501c776 Bug 1926483 - part 4: Make WSRunScanner::Scan(InclusiveNext|Previous)VisibleNodeOrBlockBoundary take WSRunScanner::Scan and ancestor limiter r=m_kato
Note that this removes a lot of `aEditingHost` params.  This may cause odd
behavior if editing host is changed by a legacy mutation event listener.
However, it'll be completely deleted soon and even if we meet some regressions,
we can just restore the param to set `aAncestorLimiter`.

Differential Revision: https://phabricator.services.mozilla.com/D233794
2025-01-23 05:01:57 +00:00
Masayuki Nakano
bf56604367 Bug 1926483 - part 2: Make WSRunScanner::Get(InclusiveNext|Previous)CharPoint free from editing host r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D233792
2025-01-23 05:01:56 +00:00
Masayuki Nakano
d36ef81488 Bug 1926483 - part 1: Make WSRunScanner instance free from editing host r=m_kato
If it scans starting from a editable point, it does not require the editing
host as an ancestor limiter.  Therefore, some users can be free from editing
host.

Differential Revision: https://phabricator.services.mozilla.com/D233791
2025-01-23 05:01:56 +00:00
Masayuki Nakano
c6b4e944ef Bug 1939220 - part 6: Make TextFragmentData free from the editing host r=m_kato
It stores the editing host. However, its role is scan the DOM from a point in
a block containing the point.  Therefore, it can know which node is editing
host when it scans without computing the editing host.  So, it does not need
to be specified the editing host.

Then, it can scan non-editable DOM too.  Therefore, this extends some utility
methods of `HTMLEditUtils` which are used by `TextFragmentData` and
`BoundaryData`.

Differential Revision: https://phabricator.services.mozilla.com/D232937
2025-01-20 08:03:59 +00:00
Masayuki Nakano
bd4fdbf30a Bug 1939220 - part 3: Make TextFragmentData::BoundaryData not depend on the editing host r=m_kato
Its role is scanning the DOM.  Therefore, it can know which node is an editing
host during a scan.  Therefore, it does not require the editing host parameter.
To fix that, some utility methods of `HTMLEditUtils` needs to work with
non-editable nodes.  Therefore, this patch also updates `HTMLEditUtils`.

Finally, this gets rid of the `NS_ASSERTION`s in the constructor of
`TextFragmentData` because it'll be available with non-editable nodes too.
Although current all callers assume that it works as in an editing host.

Differential Revision: https://phabricator.services.mozilla.com/D232934
2025-01-20 08:03:58 +00:00
Masayuki Nakano
771489d350 Bug 1939220 - part 1: Split WSRunObject files for WSRunScanner and WhiteSpaceVisibilityKeeper r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D232932
2025-01-20 08:03:57 +00:00
Sandor Molnar
11ae540bbc Backed out 6 changesets (bug 1939220) for causing build bustages CLOSED TREE
Backed out changeset b15602e6fbf5 (bug 1939220)
Backed out changeset 129d2cd2e11e (bug 1939220)
Backed out changeset b663c3b349f0 (bug 1939220)
Backed out changeset cbd9e4f12bd2 (bug 1939220)
Backed out changeset 81260f9e6677 (bug 1939220)
Backed out changeset f33e7201796d (bug 1939220)
2025-01-20 05:02:53 +02:00
Masayuki Nakano
6fd78fc633 Bug 1939220 - part 6: Make TextFragmentData free from the editing host r=m_kato
It stores the editing host. However, its role is scan the DOM from a point in
a block containing the point.  Therefore, it can know which node is editing
host when it scans without computing the editing host.  So, it does not need
to be specified the editing host.

Then, it can scan non-editable DOM too.  Therefore, this extends some utility
methods of `HTMLEditUtils` which are used by `TextFragmentData` and
`BoundaryData`.

Differential Revision: https://phabricator.services.mozilla.com/D232937
2025-01-19 23:35:36 +00:00
Masayuki Nakano
5a37bc8a95 Bug 1939220 - part 3: Make TextFragmentData::BoundaryData not depend on the editing host r=m_kato
Its role is scanning the DOM.  Therefore, it can know which node is an editing
host during a scan.  Therefore, it does not require the editing host parameter.
To fix that, some utility methods of `HTMLEditUtils` needs to work with
non-editable nodes.  Therefore, this patch also updates `HTMLEditUtils`.

Finally, this gets rid of the `NS_ASSERTION`s in the constructor of
`TextFragmentData` because it'll be available with non-editable nodes too.
Although current all callers assume that it works as in an editing host.

Differential Revision: https://phabricator.services.mozilla.com/D232934
2025-01-19 23:35:35 +00:00
Masayuki Nakano
0537c53049 Bug 1939220 - part 1: Split WSRunObject files for WSRunScanner and WhiteSpaceVisibilityKeeper r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D232932
2025-01-19 23:35:34 +00:00
Masayuki Nakano
6f4cdf57e0 Bug 1941520 - Make HTMLEditor::OnModifyDocument set top level edit sub-action before maintaining the white-space visibility r=m_kato
When pasting text, a `paste` event is fired before a `beforeinput` event.
Therefore, the editor still does not have top level edit sub-action.  Therefore,
the DOM mutation caused by the web app will be handled by
`HTMLEditor::OnModifyDocument` immediately after removing the script blocker.
At this time, we may do:
* insert a padding `<br>` if something immediately after last input is removed
* replace a collapsible white-space if padding `<br>` is removed

Then, each handler sets the top level edit sub-action and the post-processor
will run immediately.  Then, especially in the latter case,
`WhiteSpaceVisibilityKeeper::NormalizeVisibleWhiteSpacesAt` will insert a
padding `<br>` again and restores the replaced NBSP to a collapsible
white-space unexpectedly.

Therefore, if web apps trying to normalize the pasted content with removing
the pasted nodes temporarily, it may cause entering an infinite loop.

This patch makes `HTMLEditor::OnModifyDocument` set edit sub-action for the
hacks to avoid running the post-processor.

Additionally, this touches `EditorBase::DoTransactionInternal` to avoid the
assertion failure of the new test.  The assertion failure indicates a logical
bug of our basic strategy.  However, we should not touch the big design change
for now.  (Anyway, the hack should be removed as soon as possible.)

Differential Revision: https://phabricator.services.mozilla.com/D234278
2025-01-15 08:24:34 +00:00
Masayuki Nakano
6e2a06be92 Bug 1937696 - part 1: Make HTMLEditor::InsertPaddingBRElementIfNeeded insert a padding <br> rather than a normal <br> r=m_kato
Using normal `<br>` for padding `<br>` makes notifying IME of the mutation
because `ContentEventHandler` ignores only padding `<br>` elements.  Therefore,
we should make it use a padding `<br>` for hiding the mutations from IME since
IME may be confused at unexpected text change notifications.

Differential Revision: https://phabricator.services.mozilla.com/D232601
2025-01-15 00:56:03 +00:00
Masayuki Nakano
12b6be8aa3 Bug 1938862 - Create EditorBase::InsertBRElement r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D232891
2025-01-14 08:03:51 +00:00
Masayuki Nakano
fa19f63af9 Bug 1940653 - Make HTMLEditor::HandlerInsertText insert one Text when linefeeds are preformatted r=m_kato
The form of <https://discussions.apple.com/> handles newly inserted `Text` nodes
asynchronously after pasted.  Then, the text will be wrapped into `<p>`
elements.  However, the handler does not assume that multiple and consecutive
`Text` nodes are inserted by a pasting.  Therefore, they fail handling our
pasted text which was split to each line and each preformatted linefeed.

Chrome puts only one `Text` node at pasting multiline plaintext and following
this behavior fixes the issue in the form.  Therefore, we should follow the
behavior at least for now.

Differential Revision: https://phabricator.services.mozilla.com/D233619
2025-01-10 12:14:58 +00:00
Masayuki Nakano
5ac4ced59d Bug 1940620 - Make HTMLEditor::HandleInsertText try to insert a padding <br> if it replaces composition string with empty string r=m_kato
`HTMLEditor::HandleInsertText` handles empty text insertion only when it comes
from an `eCompositionChange` event.  Then, it replaces existing composition
string with empty string, i.e., delete the composition string.  Therefore, if
the previous character is a collapsible white-space, it will be invisible
if the composition string is the last content before the following block
boundary unless there is a padding `<br>`.

Differential Revision: https://phabricator.services.mozilla.com/D233613
2025-01-09 12:36:01 +00:00
Masayuki Nakano
148cf5936e Bug 1940278 - Make HTMLEditor replace collapsible ASCII white-space with an NBSP if it's visible by a following <br> but it's removed r=m_kato
This is a hack until bug 503838 is fixed.

The other browsers puts an NBSP for the last ASCII white-space immediately
before a block boundary to make it visible.  However, we currently need to
keep using an ASCII white-space as-is with putting a padding `<br>` element.

However, web apps may delete the `<br>` for some reasons without maintaining
the preceding collapsible white-space visibility since it's not required in
the other browsers.

Therefore, this patch replaces the white-spaces only when we meet such
situation.  Of course, this breaks the undo stack, but touching the DOM anyway
causes breaking the undo stack.  Thus, we can trust the web app as that it
manages their on undo stack.

Differential Revision: https://phabricator.services.mozilla.com/D233472
2025-01-09 06:48:27 +00:00
Masayuki Nakano
e9107885af Bug 1925794 - Make HTMLEditor treat mailcite element which is a blocked <span> as inline r=m_kato
The plaintext email composer inserts quoted text with a `<span>` which is
styled as `display: block`.  And it's assumed that nobody deletes its trailing
`<br>` in it.  However, we've started referring the `display` style to check
whether the element is an inline or a block (bug 1851951), and deleting padding
`<br>` elements when they become unnecessary (bug 1923251).  Therefore, the
trailing `<br>` elements may be deleted.

The `<br>` is required by the serializer to avoid its content and outer content
are both appear in the same line.  Therefore, `HTMLEditor` needs to treat a
special handling at considering unnecessary line break and considering inserting
a padding line break.

Additionally, `HTMLEditor::HandleInsertParagraphInMailCiteElement` should not
refer the computed styles.  So, this patch makes it check with the default
style.  So, this patch may include some bugs if the source comes from another
editor, but it's okay for Firefox.  So, if we need to support such edge cases,
Thunderbird should stop using `<span>` or switch the plaintext mode to use
`contenteditable="plaintext-only"` or hack the serializer.

Differential Revision: https://phabricator.services.mozilla.com/D232814
2025-01-08 00:35:19 +00:00
Masayuki Nakano
9fd27e7690 Bug 1937289 - Make AutoRangeArray::ExtendAnchorFocusRangeFor stop using nsFrameSelection r=m_kato,jjaschke,dom-core
`AutoRangeArray` is created for making some handlers of the editor classes free
from `Selection` and `nsFrameSelection` while handling the edit actions.
However, the method still depends on `nsFrameSelection` instance since its
callees are instance methods of `nsFrameSelection`.

However, `EditContext` requires completely free methods to compute target
ranges of `beforeinput`.  Therefore, we need to make it not depend on
`Selection` nor `nsFrameSelection`.

The common method, `nsFrameSelection::CreateRangeExtendedToSomewhere`, requires
`PresShell`, selection limiter which is set only when the selection is an
independent selection like in a selection for a text control, selection
ancestor limiter which is set only when an editing host has focus, caret
association hint to put caret to end of preceding line or start of following
line if selection range is collapsed at a line break and caret bidi level for
considering caret position around line break in bidi text.  They are now stored
by `nsFrameSelection` and modified when selection range is changed in some
cases.  Basically, the method is called without updating its ranges and if and
only if it's initialized with `Selection`.  So, simply caching the
`nsFrameSelection`'s values solves the issues in the most cases, but this
patch makes `AutoRangeArray` adjust the value only when its `Collapse` is
called because `Selection` automatically updates it and we can compute the
value without `Selection` nor `nsFrameSelection`.

After applying this patch, `AutoRangeArray` has two meanings, one is the
instance is a proxy for `Selection`.  The other is a container for a range to
call methods which take pointer or reference to it.  To make this differences
checked at build time, this patch creates a new subclass of it, and renamed to
`AutoClonedRangeArray` to make it clearer that what are stored in the array.

Oddly, `AutoRangeArray(nsRange&)` constructor has not been cloned.  Therefore,
I make it and its subclass version clone before storing into the array.  Then,
one caller needs to change which range should be tracked.

Differential Revision: https://phabricator.services.mozilla.com/D232174
2025-01-07 01:56:52 +00:00
Masayuki Nakano
05da8b6db0 Bug 1921180 - part 3: Make HTMLEditor use preformatted linefeeds if it's preferred r=m_kato
Currently, only the "insert line break" handler uses a preformatted linefeed
instead of `<br>` if it's better.  However, in `contenteditable="plaintext-only",
we should use preformatted linefeeds in most cases.  Therefore, we should make
them call the inserters with the `GetPreferredLineBreak` result.

Differential Revision: https://phabricator.services.mozilla.com/D231666
2024-12-24 00:21:52 +00:00
Masayuki Nakano
d6a5e03fa7 Bug 1921180 - part 2: Make HTMLEditor::HandleInsertLinefeed use InsertLineBreak with LineBreakType::Linefeed r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D231665
2024-12-24 00:21:51 +00:00
Masayuki Nakano
050416a35c Bug 1935923 - part 5: Make HTMLEditor::InsertPaddingBRElementIfNeeded return CreateLineBreakResult r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D231660
2024-12-22 01:56:39 +00:00