diff --git a/dom/base/nsPlainTextSerializer.cpp b/dom/base/nsPlainTextSerializer.cpp
index 86c70b0f3667..c299a428e400 100644
--- a/dom/base/nsPlainTextSerializer.cpp
+++ b/dom/base/nsPlainTextSerializer.cpp
@@ -22,6 +22,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/Preferences.h"
#include "mozilla/BinarySearch.h"
+#include "nsComputedDOMStyle.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -356,6 +357,7 @@ nsPlainTextSerializer::AppendElementStart(Element* aElement,
if (isContainer) {
rv = DoOpenContainer(id);
+ mPreformatStack.push(IsElementPreformatted(mElement));
}
else {
rv = DoAddLeaf(id);
@@ -389,6 +391,7 @@ nsPlainTextSerializer::AppendElementEnd(Element* aElement,
rv = NS_OK;
if (isContainer) {
rv = DoCloseContainer(id);
+ mPreformatStack.pop();
}
mElement = nullptr;
@@ -1537,7 +1540,7 @@ nsPlainTextSerializer::Write(const nsAString& aStr)
// This mustn't be mixed with intelligent wrapping without clearing
// the mCurrentLine buffer before!!!
- NS_ASSERTION(mCurrentLine.IsEmpty(),
+ NS_ASSERTION(mCurrentLine.IsEmpty() || IsInPre(),
"Mixed wrapping data and nonwrapping data on the same line");
if (!mCurrentLine.IsEmpty()) {
FlushLine();
@@ -1755,28 +1758,22 @@ nsPlainTextSerializer::GetIdForContent(nsIContent* aContent)
return localName->IsStaticAtom() ? localName : nullptr;
}
-/**
- * Returns true if we currently are inside a
. The check is done
- * by traversing the tag stack looking for
until we hit a block
- * level tag which is assumed to override any
:s below it in
- * the stack. To do this correctly to a 100% would require access
- * to style which we don't support in this converter.
- */
bool
nsPlainTextSerializer::IsInPre()
{
- int32_t i = mTagStackIndex;
- while(i > 0) {
- if (mTagStack[i - 1] == nsGkAtoms::pre)
- return true;
- if (nsContentUtils::IsHTMLBlock(mTagStack[i - 1])) {
- // We assume that every other block overrides a
- return false;
- }
- --i;
- }
+ return !mPreformatStack.empty() && mPreformatStack.top();
+}
- // Not a
in the whole stack
+bool
+nsPlainTextSerializer::IsElementPreformatted(Element* aElement)
+{
+ nsRefPtr styleContext =
+ nsComputedDOMStyle::GetStyleContextForElementNoFlush(aElement, nullptr,
+ nullptr);
+ if (styleContext) {
+ const nsStyleText* textStyle = styleContext->StyleText();
+ return textStyle->WhiteSpaceOrNewlineIsSignificant();
+ }
return false;
}
diff --git a/dom/base/nsPlainTextSerializer.h b/dom/base/nsPlainTextSerializer.h
index 65ce863e4e25..5688fed5d99c 100644
--- a/dom/base/nsPlainTextSerializer.h
+++ b/dom/base/nsPlainTextSerializer.h
@@ -22,6 +22,8 @@
#include "nsString.h"
#include "nsTArray.h"
+#include
+
class nsIContent;
namespace mozilla {
@@ -112,6 +114,9 @@ protected:
bool ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag);
+private:
+ bool IsElementPreformatted(mozilla::dom::Element* aElement);
+
protected:
nsString mCurrentLine;
uint32_t mHeadLevel;
@@ -196,6 +201,11 @@ protected:
nsIAtom** mTagStack;
uint32_t mTagStackIndex;
+ // The stack indicating whether the elements we've been operating on are
+ // CSS preformatted elements, so that we can tell if the text inside them
+ // should be formatted.
+ std::stack mPreformatStack;
+
// Content in the stack above this index should be ignored:
uint32_t mIgnoreAboveIndex;
diff --git a/dom/base/nsXHTMLContentSerializer.cpp b/dom/base/nsXHTMLContentSerializer.cpp
index 5974c254bb72..63dbbba43e72 100644
--- a/dom/base/nsXHTMLContentSerializer.cpp
+++ b/dom/base/nsXHTMLContentSerializer.cpp
@@ -33,6 +33,8 @@
#include "nsIScriptElement.h"
#include "nsAttrName.h"
#include "nsParserConstants.h"
+#include "nsComputedDOMStyle.h"
+#include "mozilla/dom/Element.h"
static const int32_t kLongLineLen = 128;
@@ -850,7 +852,7 @@ nsXHTMLContentSerializer::MaybeEnterInPreContent(nsIContent* aNode)
nsIAtom *name = aNode->Tag();
- if (name == nsGkAtoms::pre ||
+ if (IsElementPreformatted(aNode) ||
name == nsGkAtoms::script ||
name == nsGkAtoms::style ||
name == nsGkAtoms::noscript ||
@@ -868,7 +870,7 @@ nsXHTMLContentSerializer::MaybeLeaveFromPreContent(nsIContent* aNode)
}
nsIAtom *name = aNode->Tag();
- if (name == nsGkAtoms::pre ||
+ if (IsElementPreformatted(aNode) ||
name == nsGkAtoms::script ||
name == nsGkAtoms::style ||
name == nsGkAtoms::noscript ||
@@ -878,6 +880,22 @@ nsXHTMLContentSerializer::MaybeLeaveFromPreContent(nsIContent* aNode)
}
}
+bool
+nsXHTMLContentSerializer::IsElementPreformatted(nsIContent* aNode)
+{
+ if (!aNode->IsElement()) {
+ return false;
+ }
+ nsRefPtr styleContext =
+ nsComputedDOMStyle::GetStyleContextForElementNoFlush(aNode->AsElement(),
+ nullptr, nullptr);
+ if (styleContext) {
+ const nsStyleText* textStyle = styleContext->StyleText();
+ return textStyle->WhiteSpaceOrNewlineIsSignificant();
+ }
+ return false;
+}
+
void
nsXHTMLContentSerializer::SerializeLIValueAttribute(nsIContent* aElement,
nsAString& aStr)
diff --git a/dom/base/nsXHTMLContentSerializer.h b/dom/base/nsXHTMLContentSerializer.h
index d3e9d162ad8a..d885ee58b292 100644
--- a/dom/base/nsXHTMLContentSerializer.h
+++ b/dom/base/nsXHTMLContentSerializer.h
@@ -93,6 +93,10 @@ class nsXHTMLContentSerializer : public nsXMLContentSerializer {
const nsAString& aURI,
nsAString& aEscapedURI);
+private:
+ bool IsElementPreformatted(nsIContent* aNode);
+
+protected:
nsCOMPtr mEntityConverter;
/*
diff --git a/dom/base/test/copypaste.js b/dom/base/test/copypaste.js
index 8a018a34987b..d28664b29bca 100644
--- a/dom/base/test/copypaste.js
+++ b/dom/base/test/copypaste.js
@@ -160,8 +160,8 @@ function testCopyPaste (isXHTML) {
testPasteText(" Tt t t ");
copyChildrenToClipboard("div5");
- testSelectionToString(" T ");
- testClipboardValue("text/unicode", " T ");
+ testSelectionToString(" T ");
+ testClipboardValue("text/unicode", " T ");
if (isXHTML) {
testClipboardValue("text/html", "
lacinia libero ullamcorper laoreet.
Cras quis
nisi at odio
- consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
+urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
+luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at
+pharetra rutrum,
lacus risus pulvinar ante.
ut gravida eros leo ut libero
diff --git a/dom/base/test/file_htmlserializer_1_format.html b/dom/base/test/file_htmlserializer_1_format.html
index 09f80467e46e..111d7a257b56 100644
--- a/dom/base/test/file_htmlserializer_1_format.html
+++ b/dom/base/test/file_htmlserializer_1_format.html
@@ -42,11 +42,14 @@ var d = a < b && a > c;
lacinia libero ullamcorper laoreet.
- Cras quis
- nisi at odio
- consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum,
-lacus risus pulvinar ante.
-
+ Cras quis
+ nisi at odio
+ consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non
+ urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci
+ luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla
+ at pharetra rutrum,
+ lacus risus pulvinar ante.
+