This simplifies a lot position about inserting new padding line break
for the last empty line and each behavior is improved by the new API.
Differential Revision: https://phabricator.services.mozilla.com/D284965
Perhaps, we should stop using "visible" from the API names because
some API users use the methods while modifying the DOM. Therefore, the
new APIs explain the position of a line break or whether it's
significant or unnecessary from the layout point of view.
This patch adds API to check a line break position which may return
following/preceding block boundary's element and to scan following
block boundary with ignoring unnecessary line break which is done in
some places with calling
`WSRunScanner::ScanInclusiveNextVisibleNodeOrBlockBoundary()` twice.
Additionally, making the extant internal API mainly `HTMLEditUtils`
use the new API to do the correct handling.
Note that this makes `HTMLEditUtils::GetLeafNodeType` return `Ignore`
if the caller does not want invisible things and the node is in
`display:none` element. This change is required to keep passing some
tests whose editing host is `display:inline` and it's followed by
invisible text like `<script>`.
Differential Revision: https://phabricator.services.mozilla.com/D284962
The `AutoTrackDOMPoint` constructor which takes `nsCOMPtr<nsINode>&` and
`uint32_t` is not used anymore. Thus, we can get rid of the mode.
And `FlushAndStopTracking()` should be replaced with
`Flush(StopTracking::Yes)` and align the relatives to use the same
API style.
Differential Revision: https://phabricator.services.mozilla.com/D283634
Similarly, we can implement it with `LeafNodeOptions` to ignore
unnecessary nodes. Then, we can get rid of `WalkTreeOption` and
`WalkTreeOptions` completely.
Differential Revision: https://phabricator.services.mozilla.com/D277524
`WalkTreeOptions` is similar to `LeafNodeOptions` and it's hard to
maintain both of them. Additionally, `LeafNodeOptions` can specify
which type of leaf nodes should be ignored at scanning. Therefore,
`LeafNodeOptions` can be used for them.
Differential Revision: https://phabricator.services.mozilla.com/D277523
This adds some options which ignore some types of inline elements.
For example, `IgnoreAnyEmptyInlineContainers` is useful to scan previous
or next editable point because Chrome ignores empty inline elements when
deleting from next to an inline element.
`IgnoreInvisibleInlineVoidElements` is useful to scan invisible line
break from end of a block or checking a line break is invisible because
visible inline element makes a line after the last line break. E.g.,
```html
<div>ABC<br><span></span></div>
```
This shows only one line. However,
```html
<div>ABC<br><span style="border:1px solid"></span></div>
```
This shows 2 lines in the `<div>`.
Additionally, renaming the existing `LeafNodeType` values for making
them easier to understand.
Differential Revision: https://phabricator.services.mozilla.com/D277520
This reverts commit 5ccf392dce.
Revert "Bug 1998077 - part 6: Reimplement `HTMLEditUtils::Get(First|Last)Child()` and `HTMLEditUtils::Get(Next|Previous)Sibling()` with `LeafNodeOptions` r=m_kato"
This reverts commit 12eb928cb5.
Revert "Bug 1998077 - part 5: Replace the remaining `HTMLEditUtils::Get(Next|Previous)Content()` with new ones based on `Get(Next|Previous)LeafNodeOr(Next|Previous)BlockElement()` r=m_kato"
This reverts commit 58b4243d10.
Revert "Bug 1998077 - part 4: Replace some callers of `HTMLEditUtils::Get(Next|Previous)Content()` with `HTMLEditUtils::Get(Next|Previous)LeafContentOr(Next|Previous)BlockElement()` r=m_kato"
This reverts commit dd46967eb4.
Revert "Bug 1998077 - part 3: Add new options to ignore empty/invisible leaf nodes r=m_kato"
This reverts commit ca50a4a628.
Revert "Bug 1998077 - part 2: Add `WSType::EmptyInlineContainerElement` r=m_kato"
This reverts commit 4a5d93d631.
Revert "Bug 1998077 - part 1: Make `HTMLEditUtils::IsVisibleElementEvenIfLeafNode` work better if primary frame is available r=m_kato"
This reverts commit b42dc9d35f.
Similarly, we can implement it with `LeafNodeOptions` to ignore
unnecessary nodes. Then, we can get rid of `WalkTreeOption` and
`WalkTreeOptions` completely.
Differential Revision: https://phabricator.services.mozilla.com/D277524
`WalkTreeOptions` is similar to `LeafNodeOptions` and it's hard to
maintain both of them. Additionally, `LeafNodeOptions` can specify
which type of leaf nodes should be ignored at scanning. Therefore,
`LeafNodeOptions` can be used for them.
Differential Revision: https://phabricator.services.mozilla.com/D277523
This adds some options which ignore some types of inline elements.
For example, `IgnoreAnyEmptyInlineContainers` is useful to scan previous
or next editable point because Chrome ignores empty inline elements when
deleting from next to an inline element.
`IgnoreInvisibleInlineVoidElements` is useful to scan invisible line
break from end of a block or checking a line break is invisible because
visible inline element makes a line after the last line break. E.g.,
```html
<div>ABC<br><span></span></div>
```
This shows only one line. However,
```html
<div>ABC<br><span style="border:1px solid"></span></div>
```
This shows 2 lines in the `<div>`.
Additionally, renaming the existing `LeafNodeType` values for making
them easier to understand.
Differential Revision: https://phabricator.services.mozilla.com/D277520
It's not required explicitly to specify
`BlockInlineCheck::UseComputedDisplayStyle` and
`BlockInlineCheck::UseComputedDisplayOutsideStyle` to `WSRunScanner`
too. And it should take an `EnumSet` for making it easier to maintain
the class in the future.
Differential Revision: https://phabricator.services.mozilla.com/D270117
In the historical reason, some of them still take `nsINode*`. In these
days, converting from `nsINode` to `nsIContent` or `Element` is faster
than before and most callers already use `nsIContent`. Therefore, we
should make them take `const nsIContent&`.
Only some methods, allowing callers use pointer makes them simpler.
Therefore, only some methods have overloads which take
`const nsIContent*` instead.
Differential Revision: https://phabricator.services.mozilla.com/D265525
In the historical reason, some of them still take `nsINode*`. In these
days, converting from `nsINode` to `nsIContent` or `Element` is faster
than before and most callers already use `nsIContent`. Therefore, we
should make them take `const nsIContent&`.
Only some methods, allowing callers use pointer makes them simpler.
Therefore, only some methods have overloads which take
`const nsIContent*` instead.
Differential Revision: https://phabricator.services.mozilla.com/D265525
Typically, we should ignore `Comment` nodes since they are completely
invisible. One of the exceptions is, when splitting or joining its
parent, `Comment` nodes should be preserved in new container.
Therefore, the new behavior needs to be optional. So, we can start
ignoring `Comment` nodes when updating `Selection`.
Differential Revision: https://phabricator.services.mozilla.com/D257409
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
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
`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
For making most callers can insert either `<br>` or a preformatted linefeed,
the inserter should handle both of them.
This patch makes `PrepareToInsertLineBreak` which is renamed from
`PrepareToInsertBRElement` to check whether the container can have the new
line break. Then, one test starts failing, but it's okay because it's a
test in `<xmp>` which cannot have any elements, so, `<xmp>` is super legacy
element and must not be used in these days especially in editable content.
Differential Revision: https://phabricator.services.mozilla.com/D231656
For making most callers can insert either `<br>` or a preformatted linefeed,
the inserter should handle both of them.
This patch makes `PrepareToInsertLineBreak` which is renamed from
`PrepareToInsertBRElement` to check whether the container can have the new
line break. Then, one test starts failing, but it's okay because it's a
test in `<xmp>` which cannot have any elements, so, `<xmp>` is super legacy
element and must not be used in these days especially in editable content.
Differential Revision: https://phabricator.services.mozilla.com/D231656
The method caller should work with preformatted line break too. Therefore,
it should return `Maybe<EditorLineBreak>` for representing all the cases.
For the method supports to return a preformatted linefeed, this adds scanner
methods to `nsTextFragment` because calling `nsTextFragment::CharAt` a lot is
slow due to required to consider the right buffer at each call.
Differential Revision: https://phabricator.services.mozilla.com/D231655
`HTMLEditor` and its helper classes need to handle both a `<br>` and a
preformatted linefeed in the same way. However, the former is an independent
node but the latter is a char in a `Text` node. Therefore, it makes the
implementation simpler for making each `<br>` element handler treat a
preformatted linefeed in same path if there is a class to store the both
types of a line break.
Differential Revision: https://phabricator.services.mozilla.com/D231654
Unfortunately, (even tough we're the last implementor of this feature`,) there
are not editing behavior tests in web-platform tests. Therefore, this patch
creates new `plaintext-only` directory into `editing` and make the feature
enabled in its `__dir__.ini` to check the implementing behavior with new tests.
This patch also changes how to compute the editing host (whether using `<body>`
or not when selection is outside it), but the new behavior (not limited in the
`<body>`) should work fine in the most cases and I believe that it's better
than current implementation in some methods.
Note that Chrome considers whether the style should be updated or not with
the closest inclusive ancestor of the **focus node** of `Selection`. However,
it's odd and aligning to the behavior requires bigger change. Therefore, I'd
like to implement this feature only with checking the focused editing host.
Differential Revision: https://phabricator.services.mozilla.com/D223277
When it's called, it just returns at the reached content node. However, this
does not make sense when it reached a character in the text node.
Depends on D207685
Differential Revision: https://phabricator.services.mozilla.com/D207686
Currently, it checks whether `mContent` is `nullptr` or not even if the scanner
reached something. However, this makes the users of this object check whether
it has reasonable content or not and that makes the users messy. Therefore,
the scanning method should guarantee that it's always error if it does not reach
any content.
Depends on D207681
Differential Revision: https://phabricator.services.mozilla.com/D207682
The method does not assume that an inline ancestor is not a splittable, but
it may occur in the edge cases.
I tried to make `HTMLEditor` adjust selection range at starting deletion to
stop handling it or select the most distant unmodifiable element, but it
requires some expectation changes of tentative WPTs. It should be done in
a separate bug instead.
Differential Revision: https://phabricator.services.mozilla.com/D198345
Oddly, it returns the latest result as split result. However, in the case,
it splits `<kbd>` under `<button>`, but does not split `<button>`, but the
caller expects that whether it did split or not.
Differential Revision: https://phabricator.services.mozilla.com/D197262
Pasting and inserting HTML clears current style to respect the new style.
Therefore, the old ancestors shouldn't be removed when they have only
non-editable content.
Unfortunately, I have no idea how to test all of the paths which are changed
by this patch. However, I believe the method should always treat non-editable
content as visible.
Differential Revision: https://phabricator.services.mozilla.com/D196817
It means that "treat non-editable things as visible" when it's not set.
However, it's odd. You must assume that if no option is set, `IsEmpty()` etc
should treat non-editable nodes as visible things. Therefore, this renames it
to `TreatNonEditableContentAsVisible` and changing all callers of
`HTMLEditUtils::IsEmptyNode`, `HTMLEditUtils::IsEmptyInlineContainer`,
`HTMLEditUtils::IsEmptyBlockElement` and
`HTMLEditUtils::CollectEmptyInlineContainerDescendants`. So, this does not
change any behavior.
Differential Revision: https://phabricator.services.mozilla.com/D196813
Blink [1] and WebKit [2] refers `display-outside` value when they consider whether an
element is a block or an inline.
However, our editor refers HTML default style instead. Therefore, our editor
cannot handle the following cases:
* If a container block is a non-HTML element whose `display` style is `block`.
* If a container `<div>` etc is styled as `inline` and typing `Enter` in it.
* If a container `<span>` is styled as `block` and it ends with spaces.
For making users get better result, we should follow the other browsers.
However, this is too risky change. Therefore, this patch enables new behavior
only in the Nightly channel and early beta builds to collect feedback from
testers.
The big rules of checking block vs. inline are:
* When we handle block level edit actions such as formatting block, indenting
or outdenting selection, making or removing list, we should keep referring
the HTML default style because the other browsers do so and the commands are
intended for modifying the HTML structure.
* Otherwise, we should refer the computed style of the block. However, if
working with non-connected elements, we may need a special handling that is
falling back to refer the HTML default style because `HTMLEditorDataTransfer`
work with non-connected document fragments.
* Finally, if we check visibility of collapsible white-spaces and `<br>`s, we
should refer computed style. However, in this case, we may need to treat
ancestor `inline-block`s as block too, but for siblings, we should refer only
`display-outside`.
1. https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/editing/editing_utilities.cc;l=779;drc=31fb07c05718d671d96c227855bfe97af9e3fb20
2. https://searchfox.org/wubkat/rev/b054636fffeffa0314914a11ce39725a3057131e/Source/WebCore/editing/Editing.cpp#317
Differential Revision: https://phabricator.services.mozilla.com/D188598
Due to the `DOMNodeRemoved` event listener, splitting at range boundaries
may fail tracking the DOM tree due to unexpected container lost. In the
cases, the method should abort its task.
Differential Revision: https://phabricator.services.mozilla.com/D184457
Once a parent node is removed from the tree, the node may become not editable
because editable state "inherits" from ancestor nodes.
`HTMLEditor::ClearStyleAt` cleans up unnecessary parent inline elements first,
but if `<br>` element which should be reused in the block parent is contained
the inline elements, `HTMLEditUtils::IsRemovableNode()` will start returning
`false` for the `<br>` element because of in a document fragment which do not
contain an element whose `contenteditable` is `true`. Then,
`MoveNodeWithTransaction` fails to move it because of unremovable.
Therefore, this patch makes the method move `<br>` element before removing
inline elements and use `InsertNodeWithTransaction` instead if `<br>` element
is an orphan node.
Differential Revision: https://phabricator.services.mozilla.com/D182640
Now, most users of `EditorBase::IsInPlaintextMode()` are `HTMLEditor` itself.
There are some exceptions:
`EditorBase::GetDesiredSpellCheckState()` uses it to consider whether the root
(`<body>` if `HTMLEditor`) element's `specllcheck` attribute should be referred
or document's editing state. I think that this should just check
`IsHTMLEditor()`, but I think it must be okay to keep this as-is for now.
`EditorEventListener::KeyUp()` uses it to consider whether `Ctrl` + left/right
`Shift` switches the text direction of the editing host if and only if user
installed both LTR/RTL keyboard layouts and running in Windows. I think that
this should keep working in plaintext mail composer because nobody can control
the direction in plaintext editor. Therefore, this needs to check either
`IsTextEditor()` or `IsPlaintextMailComposer()` returning `true`.
`EditorEventListener::DragEventHasSupportingData()` uses it to consider
whether the editor accepts styled text and files. Therefore, it needs to check
either `IsTextEditor()` or `IsPlaintextMailComposer()` returning `false`.
Finally, we can stop setting `nsIEditor::eEditorPlaintextMask` to `TextEditor`.
Differential Revision: https://phabricator.services.mozilla.com/D181866
We have more readable and faster versions (that just omit the namespace
arg).
Mostly done via sed, with a couple helpers to use the faster lookups
where possible.
Differential Revision: https://phabricator.services.mozilla.com/D181795
It may be called with `AutoTransactionsConserveSelection` instance.
Therefore, it may return `aPoint` as-is even after modifying the DOM tree.
So it should track the point during a call of
`SplitAncestorStyledInlineElementsAt()`.
Depends on D179421
Differential Revision: https://phabricator.services.mozilla.com/D179422