Bug 1119503 - Part 2: Insert a line break between preformatted block boundaries when creating raw output; r=bzbarsky

This commit is contained in:
Ehsan Akhgari 2015-01-17 17:31:59 -05:00
parent e43a616549
commit 93488ac912
5 changed files with 44 additions and 2 deletions

View File

@ -97,7 +97,8 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
// Do the first and potentially trial encoding as preformatted and raw.
uint32_t flags = aFlags | nsIDocumentEncoder::OutputPreformatted
| nsIDocumentEncoder::OutputRaw;
| nsIDocumentEncoder::OutputRaw
| nsIDocumentEncoder::OutputForPlainTextClipboardCopy;
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
NS_ASSERTION(domDoc, "Need a document");

View File

@ -227,6 +227,13 @@ interface nsIDocumentEncoder : nsISupports
*/
const unsigned long OutputDontRemoveLineEndingSpaces = (1 << 24);
/**
* Serialize in a way that is suitable for copying a plaintext version of the
* document to the clipboard. This can for example cause line endings to be
* injected at preformatted block element boundaries.
*/
const unsigned long OutputForPlainTextClipboardCopy = (1 << 25);
/**
* Initialize with a pointer to the document and the mime type.
* @param aDocument Document to encode.

View File

@ -91,6 +91,8 @@ nsPlainTextSerializer::nsPlainTextSerializer()
mPreFormatted = false;
mStartedOutput = false;
mPreformattedBlockBoundary = false;
// initialize the tag stack to zero:
// The stack only ever contains pointers to static atoms, so they don't
// need refcounting.
@ -167,6 +169,8 @@ nsPlainTextSerializer::Init(uint32_t aFlags, uint32_t aWrapColumn,
mLineBreakDue = false;
mFloatingLines = -1;
mPreformattedBlockBoundary = false;
if (mFlags & nsIDocumentEncoder::OutputFormatted) {
// Get some prefs that controls how we do formatted output
mStructs = Preferences::GetBool(PREF_STRUCTS, mStructs);
@ -437,6 +441,16 @@ nsPlainTextSerializer::DoOpenContainer(nsIAtom* aTag)
return NS_OK;
}
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (mPreformattedBlockBoundary && DoOutput()) {
// Should always end a line, but get no more whitespace
if (mFloatingLines < 0)
mFloatingLines = 0;
mLineBreakDue = true;
}
mPreformattedBlockBoundary = false;
}
if (mFlags & nsIDocumentEncoder::OutputRaw) {
// Raw means raw. Don't even think about doing anything fancy
// here like indenting, adding line breaks or any other
@ -767,6 +781,14 @@ nsPlainTextSerializer::DoCloseContainer(nsIAtom* aTag)
return NS_OK;
}
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (DoOutput() && IsInPre() && IsElementBlock(mElement)) {
// If we're closing a preformatted block element, output a line break
// when we find a new container.
mPreformattedBlockBoundary = true;
}
}
if (mFlags & nsIDocumentEncoder::OutputRaw) {
// Raw means raw. Don't even think about doing anything fancy
// here like indenting, adding line breaks or any other
@ -1036,6 +1058,8 @@ nsPlainTextSerializer::DoAddText(bool aIsLineBreak, const nsAString& aText)
nsresult
nsPlainTextSerializer::DoAddLeaf(nsIAtom* aTag)
{
mPreformattedBlockBoundary = false;
// If we don't want any output, just return
if (!DoOutput()) {
return NS_OK;

View File

@ -170,7 +170,9 @@ private:
// While handling a new tag, this variable should remind if any line break
// is due because of a closing tag. Setting it to "TRUE" while closing the tags.
// Hence opening tags are guaranteed to start with appropriate line breaks.
bool mLineBreakDue;
bool mLineBreakDue;
bool mPreformattedBlockBoundary;
nsString mURL;
int32_t mHeaderStrategy; /* Header strategy (pref)

View File

@ -20,6 +20,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=116083
<div data-result="bar baz"><span style="white-space: pre-wrap">bar </span>baz</div>
<div data-result="bar baz"><span style="white-space: pre-line">bar </span>baz</div>
<div data-result="bar baz"><span style="white-space: -moz-pre-space">bar </span>baz</div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-wrap"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-wrap" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-line"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: pre-line" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: -moz-pre-space"><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="foo &#10; bar&#10;&#10;!&#10;&#10;&#10;baz" style="white-space: -moz-pre-space" contenteditable><div>foo </div><div> bar</div><div><br></div><div>!</div><div><br><br></div><div>baz</div></div>
<div data-result="&#10;foo bar&#10;">foo bar</div>
</div>
<script type="application/javascript">