Bug 1362858 - Part 2: Exclude script and style tags when building soft text.r=ehsan
We keep checking if a node is a text node when building soft text and
set spell checking range in DoSpellCheck. However, simply checking text
node is not optimal, we could furthur exclude text node in script and
style tags. There might be more cases we could consider to exclude.
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -1257,17 +1257,17 @@ mozInlineSpellChecker::SpellCheckBetween
// for these cases.
bool
mozInlineSpellChecker::ShouldSpellCheckNode(nsIEditor* aEditor,
nsINode *aNode)
{
MOZ_ASSERT(aNode);
if (!aNode->IsContent())
- return true;
+ return false;
nsIContent *content = aNode->AsContent();
uint32_t flags;
aEditor->GetFlags(&flags);
if (flags & nsIPlaintextEditor::eEditorMailMask) {
nsIContent *parent = content->GetParent();
while (parent) {
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -76,18 +76,21 @@ mozInlineSpellWordUtil::Init(const nsWea
nsCOMPtr<nsINode> rootNode = do_QueryInterface(rootElt);
mRootNode = rootNode;
NS_ASSERTION(mRootNode, "GetRootElement returned null *and* claimed to suceed!");
return NS_OK;
}
static inline bool
-IsTextNode(nsINode* aNode)
+IsSpellCheckingTextNode(nsINode* aNode)
{
+ nsIContent *parent = aNode->GetParent();
+ if (parent && parent->IsAnyOfHTMLElements(nsGkAtoms::script, nsGkAtoms::style))
+ return false;
return aNode->IsNodeOfType(nsINode::eTEXT);
}
typedef void (* OnLeaveNodeFunPtr)(nsINode* aNode, void* aClosure);
// Find the next node in the DOM tree in preorder.
// Calls OnLeaveNodeFunPtr when the traversal leaves a node, which is
// why we can't just use GetNextNode here, sadly.
@@ -127,32 +130,32 @@ FindNextNode(nsINode* aNode, nsINode* aR
}
// aNode is not a text node. Find the first text node starting at aNode/aOffset
// in a preorder DOM traversal.
static nsINode*
FindNextTextNode(nsINode* aNode, int32_t aOffset, nsINode* aRoot)
{
NS_PRECONDITION(aNode, "Null starting node?");
- NS_ASSERTION(!IsTextNode(aNode), "FindNextTextNode should start with a non-text node");
+ NS_ASSERTION(!IsSpellCheckingTextNode(aNode), "FindNextTextNode should start with a non-text node");
nsINode* checkNode;
// Need to start at the aOffset'th child
nsIContent* child = aNode->GetChildAt(aOffset);
if (child) {
checkNode = child;
} else {
// aOffset was beyond the end of the child list.
// goto next node after the last descendant of aNode in
// a preorder DOM traversal.
checkNode = aNode->GetNextNonChildNode(aRoot);
}
- while (checkNode && !IsTextNode(checkNode)) {
+ while (checkNode && !IsSpellCheckingTextNode(checkNode)) {
checkNode = checkNode->GetNextNode(aRoot);
}
return checkNode;
}
// mozInlineSpellWordUtil::SetEnd
//
// We have two ranges "hard" and "soft". The hard boundary is simply
@@ -174,31 +177,31 @@ nsresult
mozInlineSpellWordUtil::SetEnd(nsINode* aEndNode, int32_t aEndOffset)
{
NS_PRECONDITION(aEndNode, "Null end node?");
NS_ASSERTION(mRootNode, "Not initialized");
InvalidateWords();
- if (!IsTextNode(aEndNode)) {
+ if (!IsSpellCheckingTextNode(aEndNode)) {
// End at the start of the first text node after aEndNode/aEndOffset.
aEndNode = FindNextTextNode(aEndNode, aEndOffset, mRootNode);
aEndOffset = 0;
}
mSoftEnd = NodeOffset(aEndNode, aEndOffset);
return NS_OK;
}
nsresult
mozInlineSpellWordUtil::SetPosition(nsINode* aNode, int32_t aOffset)
{
InvalidateWords();
- if (!IsTextNode(aNode)) {
+ if (!IsSpellCheckingTextNode(aNode)) {
// Start at the start of the first text node after aNode/aOffset.
aNode = FindNextTextNode(aNode, aOffset, mRootNode);
aOffset = 0;
}
mSoftBegin = NodeOffset(aNode, aOffset);
nsresult rv = EnsureWords();
if (NS_FAILED(rv)) {
@@ -683,17 +686,17 @@ static bool
ContainsDOMWordSeparator(nsINode* aNode, int32_t aBeforeOffset,
int32_t* aSeparatorOffset)
{
if (IsBRElement(aNode)) {
*aSeparatorOffset = 0;
return true;
}
- if (!IsTextNode(aNode))
+ if (!IsSpellCheckingTextNode(aNode))
return false;
return TextNodeContainsDOMWordSeparator(aNode, aBeforeOffset,
aSeparatorOffset);
}
static bool
IsBreakElement(nsINode* aNode)
@@ -764,17 +767,17 @@ mozInlineSpellWordUtil::BuildSoftText()
// not a text node, or we run out of previous sibling nodes. In the
// event that we simply cannot find any preceding word separator, the
// offset is set to 0, and the soft text beginning node is set to the
// "most previous" text node before the original starting node, or
// kept at the original starting node if no previous text nodes exist.
if (!ContainsDOMWordSeparator(node, firstOffsetInNode - 1,
&newOffset)) {
nsINode* prevNode = node->GetPreviousSibling();
- while (prevNode && IsTextNode(prevNode)) {
+ while (prevNode && IsSpellCheckingTextNode(prevNode)) {
mSoftBegin.mNode = prevNode;
if (TextNodeContainsDOMWordSeparator(prevNode, INT32_MAX,
&newOffset)) {
break;
}
prevNode = prevNode->GetPreviousSibling();
}
}
@@ -807,17 +810,17 @@ mozInlineSpellWordUtil::BuildSoftText()
// Leave this outside the loop so large heap string allocations can be reused
// across iterations
while (node) {
if (node == mSoftEnd.mNode) {
seenSoftEnd = true;
}
bool exit = false;
- if (IsTextNode(node)) {
+ if (IsSpellCheckingTextNode(node)) {
nsIContent* content = static_cast<nsIContent*>(node);
NS_ASSERTION(content, "Where is our content?");
const nsTextFragment* textFragment = content->GetText();
NS_ASSERTION(textFragment, "Where is our text?");
int32_t lastOffsetInNode = textFragment->GetLength();
if (seenSoftEnd) {
// check whether we can stop after this