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
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
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
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
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
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 [] | b" - assert_equals: Modified text is wrong expected "a " but got "a "
FAIL execCommand("forwarddelete", false, ""): "a [] | b" - assert_equals: Modified text is wrong expected "a " but got "a "
FAIL execCommand("forwarddelete", false, ""): "a []b| c" - assert_equals: Modified text is wrong expected "a " but got "a "
FAIL execCommand("forwarddelete", false, ""): "a [] <span style=white-space:pre;> </span>" - assert_equals: expected "a <span style=\"white-space:pre;\"> </span>" but got "a <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[] <span> def</span></span>" - assert_equals: expected "<span>abc<span> def</span></span>" but got "<span>abc<span> def</span></span>"
FAIL execCommand("forwarddelete", false, ""): "<span><span>abc[] </span> def</span>" - assert_equals: expected "<span><span>abc</span> def</span>" but got "<span><span>abc</span> def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[] </span><span> def</span>" - assert_equals: expected "<span>abc</span><span> def</span>" but got "<span>abc</span><span> def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[] </span><span> def</span>" - assert_equals: expected "<span>abc </span><span> def</span>" but got "<span>abc </span><span> 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> a" - assert_equals: expected "<span style=\"white-space:pre;\"> </span> a" but got "<span style=\"white-space:pre;\"> </span> 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
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
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
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
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
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
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
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 [] | b" - assert_equals: Modified text is wrong expected "a " but got "a "
FAIL execCommand("forwarddelete", false, ""): "a [] | b" - assert_equals: Modified text is wrong expected "a " but got "a "
FAIL execCommand("forwarddelete", false, ""): "a []b| c" - assert_equals: Modified text is wrong expected "a " but got "a "
FAIL execCommand("forwarddelete", false, ""): "a [] <span style=white-space:pre;> </span>" - assert_equals: expected "a <span style=\"white-space:pre;\"> </span>" but got "a <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[] <span> def</span></span>" - assert_equals: expected "<span>abc<span> def</span></span>" but got "<span>abc<span> def</span></span>"
FAIL execCommand("forwarddelete", false, ""): "<span><span>abc[] </span> def</span>" - assert_equals: expected "<span><span>abc</span> def</span>" but got "<span><span>abc</span> def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[] </span><span> def</span>" - assert_equals: expected "<span>abc</span><span> def</span>" but got "<span>abc</span><span> def</span>"
FAIL execCommand("forwarddelete", false, ""): "<span>abc[] </span><span> def</span>" - assert_equals: expected "<span>abc </span><span> def</span>" but got "<span>abc </span><span> 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> a" - assert_equals: expected "<span style=\"white-space:pre;\"> </span> a" but got "<span style=\"white-space:pre;\"> </span> 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
`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
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
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
`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
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