mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 00:35:44 +00:00
Bug 1653534 - part 2: Add text node style check in WSRunObject.cpp
r=m_kato
Simply, if a white-space is in a preformatted text node, we shouldn't modify it for normalizing. This patch adds such checks to various points in `WSRunObject.cpp`. Differential Revision: https://phabricator.services.mozilla.com/D84319
This commit is contained in:
parent
1738b19f28
commit
7c120ffd68
@ -207,7 +207,9 @@ Result<RefPtr<Element>, nsresult> WhiteSpaceVisibilityKeeper::InsertBRElement(
|
|||||||
pointToInsert);
|
pointToInsert);
|
||||||
if (atNextCharOfInsertionPoint.IsSet() &&
|
if (atNextCharOfInsertionPoint.IsSet() &&
|
||||||
!atNextCharOfInsertionPoint.IsEndOfContainer() &&
|
!atNextCharOfInsertionPoint.IsEndOfContainer() &&
|
||||||
atNextCharOfInsertionPoint.IsCharASCIISpace()) {
|
atNextCharOfInsertionPoint.IsCharASCIISpace() &&
|
||||||
|
!EditorUtils::IsContentPreformatted(
|
||||||
|
*atNextCharOfInsertionPoint.ContainerAsText())) {
|
||||||
EditorRawDOMPointInText atPreviousCharOfNextCharOfInsertionPoint =
|
EditorRawDOMPointInText atPreviousCharOfNextCharOfInsertionPoint =
|
||||||
textFragmentDataAtInsertionPoint.GetPreviousEditableCharPoint(
|
textFragmentDataAtInsertionPoint.GetPreviousEditableCharPoint(
|
||||||
atNextCharOfInsertionPoint);
|
atNextCharOfInsertionPoint);
|
||||||
@ -578,7 +580,8 @@ nsresult WhiteSpaceVisibilityKeeper::DeletePreviousWhiteSpace(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Easy case, preformatted ws.
|
// Easy case, preformatted ws.
|
||||||
if (textFragmentDataAtDeletion.IsPreformatted()) {
|
if (EditorUtils::IsContentPreformatted(
|
||||||
|
*atPreviousCharOfStart.ContainerAsText())) {
|
||||||
if (!atPreviousCharOfStart.IsCharASCIISpace() &&
|
if (!atPreviousCharOfStart.IsCharASCIISpace() &&
|
||||||
!atPreviousCharOfStart.IsCharNBSP()) {
|
!atPreviousCharOfStart.IsCharNBSP()) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -650,7 +653,8 @@ nsresult WhiteSpaceVisibilityKeeper::DeleteInclusiveNextWhiteSpace(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Easy case, preformatted ws.
|
// Easy case, preformatted ws.
|
||||||
if (textFragmentDataAtDeletion.IsPreformatted()) {
|
if (EditorUtils::IsContentPreformatted(
|
||||||
|
*atNextCharOfStart.ContainerAsText())) {
|
||||||
if (!atNextCharOfStart.IsCharASCIISpace() &&
|
if (!atNextCharOfStart.IsCharASCIISpace() &&
|
||||||
!atNextCharOfStart.IsCharNBSP()) {
|
!atNextCharOfStart.IsCharNBSP()) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -1583,7 +1587,9 @@ WhiteSpaceVisibilityKeeper::MakeSureToKeepVisibleWhiteSpacesVisibleAfterSplit(
|
|||||||
textFragmentDataAtSplitPoint.GetInclusiveNextEditableCharPoint(
|
textFragmentDataAtSplitPoint.GetInclusiveNextEditableCharPoint(
|
||||||
pointToSplit);
|
pointToSplit);
|
||||||
if (atNextCharOfStart.IsSet() && !atNextCharOfStart.IsEndOfContainer() &&
|
if (atNextCharOfStart.IsSet() && !atNextCharOfStart.IsEndOfContainer() &&
|
||||||
atNextCharOfStart.IsCharASCIISpace()) {
|
atNextCharOfStart.IsCharASCIISpace() &&
|
||||||
|
!EditorUtils::IsContentPreformatted(
|
||||||
|
*atNextCharOfStart.ContainerAsText())) {
|
||||||
// pointToSplit will be referred bellow so that we need to keep
|
// pointToSplit will be referred bellow so that we need to keep
|
||||||
// it a valid point.
|
// it a valid point.
|
||||||
AutoEditorDOMPointChildInvalidator forgetChild(pointToSplit);
|
AutoEditorDOMPointChildInvalidator forgetChild(pointToSplit);
|
||||||
@ -1620,7 +1626,9 @@ WhiteSpaceVisibilityKeeper::MakeSureToKeepVisibleWhiteSpacesVisibleAfterSplit(
|
|||||||
textFragmentDataAtSplitPoint.GetPreviousEditableCharPoint(pointToSplit);
|
textFragmentDataAtSplitPoint.GetPreviousEditableCharPoint(pointToSplit);
|
||||||
if (atPreviousCharOfStart.IsSet() &&
|
if (atPreviousCharOfStart.IsSet() &&
|
||||||
!atPreviousCharOfStart.IsEndOfContainer() &&
|
!atPreviousCharOfStart.IsEndOfContainer() &&
|
||||||
atPreviousCharOfStart.IsCharASCIISpace()) {
|
atPreviousCharOfStart.IsCharASCIISpace() &&
|
||||||
|
!EditorUtils::IsContentPreformatted(
|
||||||
|
*atPreviousCharOfStart.ContainerAsText())) {
|
||||||
if (atPreviousCharOfStart.IsStartOfContainer() ||
|
if (atPreviousCharOfStart.IsStartOfContainer() ||
|
||||||
atPreviousCharOfStart.IsPreviousCharASCIISpace()) {
|
atPreviousCharOfStart.IsPreviousCharASCIISpace()) {
|
||||||
atPreviousCharOfStart =
|
atPreviousCharOfStart =
|
||||||
@ -1816,6 +1824,9 @@ WSRunScanner::TextFragmentData::GetEndOfCollapsibleASCIIWhiteSpaces(
|
|||||||
MOZ_ASSERT(aPointAtASCIIWhiteSpace.IsSet());
|
MOZ_ASSERT(aPointAtASCIIWhiteSpace.IsSet());
|
||||||
MOZ_ASSERT(!aPointAtASCIIWhiteSpace.IsEndOfContainer());
|
MOZ_ASSERT(!aPointAtASCIIWhiteSpace.IsEndOfContainer());
|
||||||
MOZ_ASSERT(aPointAtASCIIWhiteSpace.IsCharASCIISpace());
|
MOZ_ASSERT(aPointAtASCIIWhiteSpace.IsCharASCIISpace());
|
||||||
|
NS_ASSERTION(!EditorUtils::IsContentPreformatted(
|
||||||
|
*aPointAtASCIIWhiteSpace.ContainerAsText()),
|
||||||
|
"aPointAtASCIIWhiteSpace should be in a formatted text node");
|
||||||
|
|
||||||
// If it's not the last character in the text node, let's scan following
|
// If it's not the last character in the text node, let's scan following
|
||||||
// characters in it.
|
// characters in it.
|
||||||
@ -1844,15 +1855,17 @@ WSRunScanner::TextFragmentData::GetEndOfCollapsibleASCIIWhiteSpaces(
|
|||||||
return afterLastWhiteSpace;
|
return afterLastWhiteSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can ignore empty text nodes.
|
// We can ignore empty text nodes (even if it's preformatted).
|
||||||
if (atStartOfNextTextNode.IsContainerEmpty()) {
|
if (atStartOfNextTextNode.IsContainerEmpty()) {
|
||||||
atEndOfPreviousTextNode = atStartOfNextTextNode;
|
atEndOfPreviousTextNode = atStartOfNextTextNode;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If next node starts with non-white-space character, return end of
|
// If next node starts with non-white-space character or next node is
|
||||||
// previous text node.
|
// preformatted, return end of previous text node.
|
||||||
if (!atStartOfNextTextNode.IsCharASCIISpace()) {
|
if (!atStartOfNextTextNode.IsCharASCIISpace() ||
|
||||||
|
EditorUtils::IsContentPreformatted(
|
||||||
|
*atStartOfNextTextNode.ContainerAsText())) {
|
||||||
return afterLastWhiteSpace;
|
return afterLastWhiteSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1877,6 +1890,9 @@ WSRunScanner::TextFragmentData::GetFirstASCIIWhiteSpacePointCollapsedTo(
|
|||||||
MOZ_ASSERT(aPointAtASCIIWhiteSpace.IsSet());
|
MOZ_ASSERT(aPointAtASCIIWhiteSpace.IsSet());
|
||||||
MOZ_ASSERT(!aPointAtASCIIWhiteSpace.IsEndOfContainer());
|
MOZ_ASSERT(!aPointAtASCIIWhiteSpace.IsEndOfContainer());
|
||||||
MOZ_ASSERT(aPointAtASCIIWhiteSpace.IsCharASCIISpace());
|
MOZ_ASSERT(aPointAtASCIIWhiteSpace.IsCharASCIISpace());
|
||||||
|
NS_ASSERTION(!EditorUtils::IsContentPreformatted(
|
||||||
|
*aPointAtASCIIWhiteSpace.ContainerAsText()),
|
||||||
|
"aPointAtASCIIWhiteSpace should be in a formatted text node");
|
||||||
|
|
||||||
// If there is some characters before it, scan it in the text node first.
|
// If there is some characters before it, scan it in the text node first.
|
||||||
if (!aPointAtASCIIWhiteSpace.IsStartOfContainer()) {
|
if (!aPointAtASCIIWhiteSpace.IsStartOfContainer()) {
|
||||||
@ -1904,15 +1920,17 @@ WSRunScanner::TextFragmentData::GetFirstASCIIWhiteSpacePointCollapsedTo(
|
|||||||
return atLastWhiteSpace;
|
return atLastWhiteSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can ignore empty text nodes.
|
// We can ignore empty text nodes (even if it's preformatted).
|
||||||
if (atLastCharOfNextTextNode.IsContainerEmpty()) {
|
if (atLastCharOfNextTextNode.IsContainerEmpty()) {
|
||||||
atStartOfPreviousTextNode = atLastCharOfNextTextNode;
|
atStartOfPreviousTextNode = atLastCharOfNextTextNode;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If next node ends with non-white-space character, return start of
|
// If next node ends with non-white-space character or next node is
|
||||||
// previous text node.
|
// preformatted, return start of previous text node.
|
||||||
if (!atLastCharOfNextTextNode.IsCharASCIISpace()) {
|
if (!atLastCharOfNextTextNode.IsCharASCIISpace() ||
|
||||||
|
EditorUtils::IsContentPreformatted(
|
||||||
|
*atLastCharOfNextTextNode.ContainerAsText())) {
|
||||||
return atLastWhiteSpace;
|
return atLastWhiteSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2135,9 +2153,11 @@ nsresult WhiteSpaceVisibilityKeeper::NormalizeVisibleWhiteSpacesAt(
|
|||||||
// XXX This is different behavior from Blink. Blink generates pairs of
|
// XXX This is different behavior from Blink. Blink generates pairs of
|
||||||
// an NBSP and an ASCII white-space, but put NBSP at the end of the
|
// an NBSP and an ASCII white-space, but put NBSP at the end of the
|
||||||
// sequence. We should follow the behavior for web-compat.
|
// sequence. We should follow the behavior for web-compat.
|
||||||
if (textFragmentData.IsPreformatted() || maybeNBSPFollowingVisibleContent ||
|
if (maybeNBSPFollowingVisibleContent || !isPreviousCharASCIIWhiteSpace ||
|
||||||
!isPreviousCharASCIIWhiteSpace ||
|
!followedByVisibleContentOrBRElement ||
|
||||||
!followedByVisibleContentOrBRElement) {
|
EditorUtils::IsContentPreformatted(
|
||||||
|
*atPreviousCharOfPreviousCharOfEndOfVisibleWhiteSpaces
|
||||||
|
.GetContainerAsText())) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2262,13 +2282,22 @@ EditorDOMPointInText WSRunScanner::TextFragmentData::
|
|||||||
EditorDOMPointInText atPreviousChar =
|
EditorDOMPointInText atPreviousChar =
|
||||||
GetPreviousEditableCharPoint(aPointToInsert);
|
GetPreviousEditableCharPoint(aPointToInsert);
|
||||||
if (!atPreviousChar.IsSet() || atPreviousChar.IsEndOfContainer() ||
|
if (!atPreviousChar.IsSet() || atPreviousChar.IsEndOfContainer() ||
|
||||||
!atPreviousChar.IsCharNBSP()) {
|
!atPreviousChar.IsCharNBSP() ||
|
||||||
|
EditorUtils::IsContentPreformatted(*atPreviousChar.ContainerAsText())) {
|
||||||
return EditorDOMPointInText();
|
return EditorDOMPointInText();
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorDOMPointInText atPreviousCharOfPreviousChar =
|
EditorDOMPointInText atPreviousCharOfPreviousChar =
|
||||||
GetPreviousEditableCharPoint(atPreviousChar);
|
GetPreviousEditableCharPoint(atPreviousChar);
|
||||||
if (atPreviousCharOfPreviousChar.IsSet()) {
|
if (atPreviousCharOfPreviousChar.IsSet()) {
|
||||||
|
// If the previous char is in different text node and it's preformatted,
|
||||||
|
// we shouldn't touch it.
|
||||||
|
if (atPreviousChar.ContainerAsText() !=
|
||||||
|
atPreviousCharOfPreviousChar.ContainerAsText() &&
|
||||||
|
EditorUtils::IsContentPreformatted(
|
||||||
|
*atPreviousCharOfPreviousChar.ContainerAsText())) {
|
||||||
|
return EditorDOMPointInText();
|
||||||
|
}
|
||||||
// If the previous char of the NBSP at previous position of aPointToInsert
|
// If the previous char of the NBSP at previous position of aPointToInsert
|
||||||
// is an ASCII white-space, we don't need to replace it with same character.
|
// is an ASCII white-space, we don't need to replace it with same character.
|
||||||
if (!atPreviousCharOfPreviousChar.IsEndOfContainer() &&
|
if (!atPreviousCharOfPreviousChar.IsEndOfContainer() &&
|
||||||
@ -2308,13 +2337,22 @@ EditorDOMPointInText WSRunScanner::TextFragmentData::
|
|||||||
EditorDOMPointInText atNextChar =
|
EditorDOMPointInText atNextChar =
|
||||||
GetInclusiveNextEditableCharPoint(aPointToInsert);
|
GetInclusiveNextEditableCharPoint(aPointToInsert);
|
||||||
if (!atNextChar.IsSet() || NS_WARN_IF(atNextChar.IsEndOfContainer()) ||
|
if (!atNextChar.IsSet() || NS_WARN_IF(atNextChar.IsEndOfContainer()) ||
|
||||||
!atNextChar.IsCharNBSP()) {
|
!atNextChar.IsCharNBSP() ||
|
||||||
|
EditorUtils::IsContentPreformatted(*atNextChar.ContainerAsText())) {
|
||||||
return EditorDOMPointInText();
|
return EditorDOMPointInText();
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorDOMPointInText atNextCharOfNextCharOfNBSP =
|
EditorDOMPointInText atNextCharOfNextCharOfNBSP =
|
||||||
GetInclusiveNextEditableCharPoint(atNextChar.NextPoint());
|
GetInclusiveNextEditableCharPoint(atNextChar.NextPoint());
|
||||||
if (atNextCharOfNextCharOfNBSP.IsSet()) {
|
if (atNextCharOfNextCharOfNBSP.IsSet()) {
|
||||||
|
// If the next char is in different text node and it's preformatted,
|
||||||
|
// we shouldn't touch it.
|
||||||
|
if (atNextChar.ContainerAsText() !=
|
||||||
|
atNextCharOfNextCharOfNBSP.ContainerAsText() &&
|
||||||
|
EditorUtils::IsContentPreformatted(
|
||||||
|
*atNextCharOfNextCharOfNBSP.ContainerAsText())) {
|
||||||
|
return EditorDOMPointInText();
|
||||||
|
}
|
||||||
// If following character of an NBSP is an ASCII white-space, we don't
|
// If following character of an NBSP is an ASCII white-space, we don't
|
||||||
// need to replace it with same character.
|
// need to replace it with same character.
|
||||||
if (!atNextCharOfNextCharOfNBSP.IsEndOfContainer() &&
|
if (!atNextCharOfNextCharOfNBSP.IsEndOfContainer() &&
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
[white-spaces-after-execCommand-delete.tentative.html]
|
[white-spaces-after-execCommand-delete.tentative.html]
|
||||||
prefs: [editor.white_space_normalization.blink_compatible:true]
|
prefs: [editor.white_space_normalization.blink_compatible:true]
|
||||||
|
max-asserts: 3
|
||||||
[execCommand("delete", false, ""): "a [\]<span style=white-space:pre;> </span>"]
|
[execCommand("delete", false, ""): "a [\]<span style=white-space:pre;> </span>"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
@ -300,9 +301,6 @@
|
|||||||
[execCommand("delete", false, ""): " [\]b" (length of whiteSpace sequence: 10)]
|
[execCommand("delete", false, ""): " [\]b" (length of whiteSpace sequence: 10)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[execCommand("delete", false, ""): "<span style=white-space:pre;> </span>[\] a"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[execCommand("delete", false, ""): " [\] b" (length of whiteSpace sequence: 10)]
|
[execCommand("delete", false, ""): " [\] b" (length of whiteSpace sequence: 10)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
[white-spaces-after-execCommand-forwarddelete.tentative.html]
|
[white-spaces-after-execCommand-forwarddelete.tentative.html]
|
||||||
prefs: [editor.white_space_normalization.blink_compatible:true]
|
prefs: [editor.white_space_normalization.blink_compatible:true]
|
||||||
|
max-asserts: 3
|
||||||
[execCommand("forwarddelete", false, ""): " [\] b" (length of whitespace sequence: 10)]
|
[execCommand("forwarddelete", false, ""): " [\] b" (length of whitespace sequence: 10)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -114,9 +114,6 @@
|
|||||||
[execCommand("inserttext", false, " ") at "a<span>b[\]</span><span><span> c</span></span>"]
|
[execCommand("inserttext", false, " ") at "a<span>b[\]</span><span><span> c</span></span>"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[execCommand("inserttext", false, "\\u00A0") at "a [\]<span style=white-space:pre> </span>"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[execCommand("inserttext", false, " ") at "a[\]<span style=white-space:pre>b</span>"]
|
[execCommand("inserttext", false, " ") at "a[\]<span style=white-space:pre>b</span>"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
@ -138,9 +135,6 @@
|
|||||||
[execCommand("inserttext", false, " ") at "a<span><span>b[\]</span></span><span> c</span>"]
|
[execCommand("inserttext", false, " ") at "a<span><span>b[\]</span></span><span> c</span>"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[execCommand("inserttext", false, " ") at "a [\]<span style=white-space:pre> </span>"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[execCommand("inserttext", false, " ") at "a [\] b"]
|
[execCommand("inserttext", false, " ") at "a [\] b"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
@ -207,21 +201,6 @@
|
|||||||
[execCommand("inserttext", false, "\\u00A0") at "a[\]<span style=white-space:pre> </span>"]
|
[execCommand("inserttext", false, "\\u00A0") at "a[\]<span style=white-space:pre> </span>"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[execCommand("inserttext", false, " ") at "a [\]<span style=white-space:pre> </span>"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[execCommand("inserttext", false, " ") at "a [\]<span style=white-space:pre> </span>"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[execCommand("inserttext", false, "\\u00A0") at "a [\]<span style=white-space:pre> </span>"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[execCommand("inserttext", false, " ") at "a [\]<span style=white-space:pre> </span>"]
|
[execCommand("inserttext", false, " ") at "a [\]<span style=white-space:pre> </span>"]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[execCommand("inserttext", false, "\\u00A0") at "a [\]<span style=white-space:pre> </span>"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[execCommand("inserttext", false, "\\u00A0") at "a [\]<span style=white-space:pre> </span>"]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
@ -32,9 +32,6 @@
|
|||||||
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<span>foo[\]</span>" compare innerHTML]
|
[[["defaultparagraphseparator","p"\],["insertparagraph",""\]\] "<span>foo[\]</span>" compare innerHTML]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[[["insertparagraph",""\]\] "<pre>foo[\] </pre>" compare innerHTML]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[[["insertparagraph",""\]\] "<xmp>foo[\]bar</xmp>" compare innerHTML]
|
[[["insertparagraph",""\]\] "<xmp>foo[\]bar</xmp>" compare innerHTML]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user