44439: Support headers (3 modes), <dd>/<dt>, <q>, <code>, <th>.

Improved <img>, </blockquote>.
Improved "unknown" block and (some) inline tags.
Pref for structured phrases.
r=akk, a=waterson


git-svn-id: svn://10.0.0.236/trunk@75106 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mozilla.BenB%bucksch.org
2000-07-28 23:18:12 +00:00
parent 3cb50139c9
commit 7796c1500d
7 changed files with 400 additions and 84 deletions

View File

@@ -52,17 +52,31 @@
#include "nsLWBrkCIID.h"
#include "nsIOutputStream.h"
#include "nsFileStream.h"
#include "nsIPref.h"
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
static NS_DEFINE_CID(kLWBrkCID, NS_LWBRK_CID);
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
#define PREF_STRUCTS "converter.html2txt.structs"
#define PREF_HEADER_STRATEGY "converter.html2txt.header_strategy"
const PRInt32 gTabSize=4;
const PRInt32 gOLNumberWidth = 3;
const PRInt32 gIndentSizeHeaders = 2; /* Indention of h1, if
mHeaderStrategy = 1 or = 2.
Indention of other headers
is derived from that.
XXX center h1? */
const PRInt32 gIndentIncrementHeaders = 2; /* If mHeaderStrategy = 1,
indent h(x+1) this many
columns more than h(x) */
const PRInt32 gIndentSizeList = (gTabSize > gOLNumberWidth+3) ? gTabSize: gOLNumberWidth+3;
// Indention of non-first lines of ul and ol
const PRInt32 gIndentSizeDD = gTabSize; // Indention of <dd>
static PRBool IsInline(eHTMLTags aTag);
static PRBool IsBlockLevel(eHTMLTags aTag);
static PRInt32 HeaderLevel(eHTMLTags aTag);
static PRInt32 unicharwidth(PRUnichar ucs);
static PRInt32 unicharwidth(const PRUnichar* pwcs, PRInt32 n);
@@ -181,6 +195,10 @@ nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream()
mBufferLength = 0;
mBuffer = nsnull;
mUnicodeEncoder = nsnull;
mStructs = PR_TRUE; // will be read from prefs later
mHeaderStrategy = 1 /*indent increasingly*/; // ditto
for (PRInt32 i = 0; i <= 6; i++)
mHeaderCounter[i] = 0;
// Line breaker
mLineBreaker = nsnull;
@@ -273,6 +291,15 @@ nsHTMLToTXTSinkStream::Initialize(nsIOutputStream* aOutStream,
else
mLineBreak.AssignWithConversion(NS_LINEBREAK); // Platform/default
// Get some prefs
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
if (NS_SUCCEEDED(rv) && prefs)
{
rv = prefs->GetBoolPref(PREF_STRUCTS, &mStructs);
rv = prefs->GetIntPref(PREF_HEADER_STRATEGY, &mHeaderStrategy);
}
return result;
}
@@ -514,7 +541,6 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
PRInt32 whitespace;
if(NS_SUCCEEDED(GetValueOfAttribute(aNode, "style", style)) &&
(-1 != (whitespace = style.Find("white-space:"))))
/* DELETEME: What, if the style is defined in an external stylesheet? */
{
if (-1 != style.Find("-moz-pre-wrap", PR_TRUE, whitespace))
{
@@ -569,19 +595,51 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
if (type == eHTMLTag_p || type == eHTMLTag_pre)
EnsureVerticalSpace(1); // Should this be 0 in unformatted case?
// Else make sure we'll separate block level tags,
// even if we're about to leave before doing any other formatting.
// Oddly, I can't find a case where this actually makes any difference.
//else if (IsBlockLevel(type))
// EnsureVerticalSpace(0);
// even if we're about to leave, before doing any other formatting.
else if (IsBlockLevel(type))
EnsureVerticalSpace(0);
// The rest of this routine is formatted output stuff,
// which we should skip if we're not formatted:
if (!(mFlags & nsIDocumentEncoder::OutputFormatted))
return NS_OK;
if (type == eHTMLTag_ul)
if (type == eHTMLTag_h1 || type == eHTMLTag_h2 ||
type == eHTMLTag_h3 || type == eHTMLTag_h4 ||
type == eHTMLTag_h5 || type == eHTMLTag_h6)
{
EnsureVerticalSpace(2);
if (mHeaderStrategy == 2) // numbered
{
mIndent += gIndentSizeHeaders;
// Caching
nsCAutoString leadup;
PRInt32 level = HeaderLevel(type);
// Increase counter for current level
mHeaderCounter[level]++;
// Reset all lower levels
PRInt32 i;
for (i = level + 1; i <= 6; i++)
mHeaderCounter[i] = 0;
// Construct numbers
for (i = 1; i <= level; i++)
{
leadup.AppendInt(mHeaderCounter[i]);
leadup += ".";
}
leadup += " ";
Write(NS_ConvertASCIItoUCS2(leadup.GetBuffer()));
}
else if (mHeaderStrategy == 1) // indent increasingly
{
mIndent += gIndentSizeHeaders;
for (PRInt32 i = HeaderLevel(type); i > 1; i--)
// for h(x), run x-1 times
mIndent += gIndentIncrementHeaders;
}
}
else if (type == eHTMLTag_ul)
{
// Indent here to support nested list, which aren't included in li :-(
EnsureVerticalSpace(1); // Must end the current line before we change indent.
@@ -612,7 +670,11 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
mInIndentString.AppendWithConversion(' ');
}
else if (type == eHTMLTag_td)
else if (type == eHTMLTag_dl)
EnsureVerticalSpace(1);
else if (type == eHTMLTag_dd)
mIndent += gIndentSizeDD;
else if (type == eHTMLTag_td || type == eHTMLTag_th)
{
// We must make sure that the content of two table cells get a
// space between them.
@@ -653,30 +715,39 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
}
else if (type == eHTMLTag_img)
{
nsAutoString url;
if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "src", url)) && !url.IsEmpty())
/* Output (in decreasing order of preference)
alt, title or src (URI) attribute */
// See <http://www.w3.org/TR/REC-html40/struct/objects.html#edef-IMG>
nsAutoString desc, temp;
if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "alt", desc)))
{
nsAutoString temp, desc;
if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "alt", desc))
&& !desc.IsEmpty())
if (!desc.IsEmpty())
{
temp.AppendWithConversion(" (");
temp.AppendWithConversion(" ["); // Should we output chars at all here?
desc.StripChars("\"");
temp += desc;
temp.AppendWithConversion(" <");
url.StripChars("\"");
temp += url;
temp.AppendWithConversion(">) ");
temp.AppendWithConversion(" ]");
}
else
{
temp.AppendWithConversion(" <");
url.StripChars("\"");
temp += url;
temp.AppendWithConversion("> ");
}
Write(temp);
// If the alt attribute has an empty value (|alt=""|), output nothing
}
else if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "title", desc))
&& !desc.IsEmpty())
{
temp.AppendWithConversion(" [");
desc.StripChars("\"");
temp += desc;
temp.AppendWithConversion("] ");
}
else if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "src", desc))
&& !desc.IsEmpty())
{
temp.AppendWithConversion(" <");
desc.StripChars("\"");
temp += desc;
temp.AppendWithConversion("> ");
}
if (!temp.IsEmpty())
Write(temp);
}
else if (type == eHTMLTag_a && !IsConverted(aNode))
{
@@ -688,15 +759,21 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
mURL = url;
}
}
else if (type == eHTMLTag_sup && !IsConverted(aNode))
else if (type == eHTMLTag_q)
Write(NS_ConvertASCIItoUCS2("\""));
else if (type == eHTMLTag_sup && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("^"));
else if (type == eHTMLTag_sub && !IsConverted(aNode))
else if (type == eHTMLTag_sub && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("_"));
else if ((type ==eHTMLTag_strong || type==eHTMLTag_b) && !IsConverted(aNode))
else if (type == eHTMLTag_code && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("|"));
else if ((type == eHTMLTag_strong || type == eHTMLTag_b)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("*"));
else if ((type == eHTMLTag_em || type == eHTMLTag_i) && !IsConverted(aNode))
else if ((type == eHTMLTag_em || type == eHTMLTag_i)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("/"));
else if (type == eHTMLTag_u && !IsConverted(aNode))
else if (type == eHTMLTag_u && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("_"));
return NS_OK;
@@ -729,6 +806,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
FlushLine();
} else if ((type == eHTMLTag_tr) ||
(type == eHTMLTag_li) ||
(type == eHTMLTag_dt) ||
(type == eHTMLTag_dd) ||
(type == eHTMLTag_pre) ||
(type == eHTMLTag_blockquote)) {
EnsureVerticalSpace(0);
@@ -737,7 +816,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
// in formatted mode, otherwise 0.
// This is hard. Sometimes 0 is a better number, but
// how to know?
EnsureVerticalSpace((mFlags & nsIDocumentEncoder::OutputFormatted) ? 1 : 0);
EnsureVerticalSpace((mFlags & nsIDocumentEncoder::OutputFormatted)
? 1 : 0);
}
}
@@ -746,7 +826,21 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
if (!(mFlags & nsIDocumentEncoder::OutputFormatted))
return NS_OK;
if (type == eHTMLTag_ul)
if (type == eHTMLTag_h1 || type == eHTMLTag_h2 ||
type == eHTMLTag_h3 || type == eHTMLTag_h4 ||
type == eHTMLTag_h5 || type == eHTMLTag_h6)
{
if (mHeaderStrategy /*numbered or indent increasingly*/ )
mIndent -= gIndentSizeHeaders;
if (mHeaderStrategy == 1 /*indent increasingly*/ )
{
for (PRInt32 i = HeaderLevel(type); i > 1; i--)
// for h(x), run x-1 times
mIndent -= gIndentIncrementHeaders;
}
EnsureVerticalSpace(1);
}
else if (type == eHTMLTag_ul)
{
mIndent -= gIndentSizeList;
}
@@ -756,12 +850,21 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
--mOLStackIndex;
mIndent -= gIndentSizeList;
}
else if (type == eHTMLTag_dd)
{
mIndent -= gIndentSizeDD;
}
else if (type == eHTMLTag_blockquote)
{
FlushLine();
if (mCiteQuoteLevel>0)
nsString value;
nsresult rv = GetValueOfAttribute(aNode, "type", value);
if ( NS_SUCCEEDED(rv) )
value.StripChars("\"");
if (NS_SUCCEEDED(rv) && value.EqualsWithConversion("cite", PR_TRUE))
mCiteQuoteLevel--;
else if(mIndent >= gTabSize)
else
mIndent -= gTabSize;
}
else if (type == eHTMLTag_a && !IsConverted(aNode) && !mURL.IsEmpty())
@@ -772,13 +875,20 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
Write(temp);
mURL.Truncate();
}
else if ((type== eHTMLTag_sup || type== eHTMLTag_sub) && !IsConverted(aNode))
else if (type == eHTMLTag_q)
Write(NS_ConvertASCIItoUCS2("\""));
else if ((type == eHTMLTag_sup || type == eHTMLTag_sub)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2(" "));
else if ((type== eHTMLTag_strong || type==eHTMLTag_b) && !IsConverted(aNode))
else if (type == eHTMLTag_code && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("|"));
else if ((type == eHTMLTag_strong || type == eHTMLTag_b)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("*"));
else if ((type == eHTMLTag_em || type == eHTMLTag_i) && !IsConverted(aNode))
else if ((type == eHTMLTag_em || type == eHTMLTag_i)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("/"));
else if (type == eHTMLTag_u && !IsConverted(aNode))
else if (type == eHTMLTag_u && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("_"));
return NS_OK;
@@ -887,6 +997,7 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode)
EnsureVerticalSpace(0);
// Make a line of dashes as wide as the wrap width
// XXX honoring percentage would be nice
nsAutoString line;
PRUint32 width = (mWrapColumn > 0 ? mWrapColumn : 25);
while (line.Length() < width)
@@ -1483,20 +1594,23 @@ PRBool IsInline(eHTMLTags aTag)
{
case eHTMLTag_a:
case eHTMLTag_address:
case eHTMLTag_b:
case eHTMLTag_big:
case eHTMLTag_blink:
case eHTMLTag_b:
case eHTMLTag_br:
case eHTMLTag_cite:
case eHTMLTag_code:
case eHTMLTag_dfn:
case eHTMLTag_del:
case eHTMLTag_em:
case eHTMLTag_font:
case eHTMLTag_img:
case eHTMLTag_i:
case eHTMLTag_img:
case eHTMLTag_ins:
case eHTMLTag_kbd:
case eHTMLTag_keygen:
case eHTMLTag_nobr:
case eHTMLTag_q:
case eHTMLTag_samp:
case eHTMLTag_small:
case eHTMLTag_spacer:
@@ -1507,6 +1621,7 @@ PRBool IsInline(eHTMLTags aTag)
case eHTMLTag_sup:
case eHTMLTag_td:
case eHTMLTag_textarea:
case eHTMLTag_th:
case eHTMLTag_tt:
case eHTMLTag_u:
case eHTMLTag_var:
@@ -1523,6 +1638,36 @@ PRBool IsInline(eHTMLTags aTag)
PRBool IsBlockLevel(eHTMLTags aTag)
{
return !IsInline(aTag);
/* XXX Note: We output linebreaks for blocks.
I.e. we output linebreaks for "unknown" inline tags.
I just hunted such a bug for <q>, same for <ins>, <col> etc..
Better fallback to inline. /BenB */
}
/*
@return 0 = no header, 1 = h1, ..., 6 = h6
*/
PRInt32 HeaderLevel(eHTMLTags aTag)
{
PRInt32 result;
switch (aTag)
{
case eHTMLTag_h1:
result = 1; break;
case eHTMLTag_h2:
result = 2; break;
case eHTMLTag_h3:
result = 3; break;
case eHTMLTag_h4:
result = 4; break;
case eHTMLTag_h5:
result = 5; break;
case eHTMLTag_h6:
result = 6; break;
default:
result = 0; break;
}
return result;
}
PRBool nsHTMLToTXTSinkStream::MayWrap()

View File

@@ -189,6 +189,17 @@ protected:
PRBool mStartedOutput; // we've produced at least a character
nsString mURL;
PRInt32 mStructs; // Output structs (pref)
PRBool mHeaderStrategy; /* Header strategy (pref)
0 = no indention
1 = indention, increased with
header level (default)
2 = numbering and slight indention */
PRInt32 mHeaderCounter[7]; /* For header-numbering:
Number of previous headers of
the same depth and in the same
section.
mHeaderCounter[1] for <h1> etc. */
// The tag stack: the stack of tags we're operating on, so we can nest:
nsHTMLTag *mTagStack;

View File

@@ -1,5 +1,6 @@
Simple html page
Simple html page
Here is a link to the mozilla.org <http://www.mozilla.org> page. Here
is some _underlined and *bold*ened_ified text plus some <angle bracket
entities>.

View File

@@ -301,6 +301,8 @@ pref("signon.rememberSignons", true);
pref("network.sendRefererHeader", 2); // 0=don't send any, 1=send only on clicks, 2=send on image requests as well
pref("network.enablePad", false); // Allow client to do proxy autodiscovery
pref("network.padPacURL", ""); // The proxy autodiscovery url
pref("converter.html2txt.structs", true); // Output structured phrases (strong, em, code, sub, sup, b, i, u)
pref("converter.html2txt.header_strategy", 1); // 0 = no indention; 1 = indention, increased with header level; 2 = numbering and slight indention
pref("wallet.captureForms", true);
pref("wallet.notified", false);
pref("wallet.fetchPatches", false);

View File

@@ -52,17 +52,31 @@
#include "nsLWBrkCIID.h"
#include "nsIOutputStream.h"
#include "nsFileStream.h"
#include "nsIPref.h"
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
static NS_DEFINE_CID(kLWBrkCID, NS_LWBRK_CID);
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
#define PREF_STRUCTS "converter.html2txt.structs"
#define PREF_HEADER_STRATEGY "converter.html2txt.header_strategy"
const PRInt32 gTabSize=4;
const PRInt32 gOLNumberWidth = 3;
const PRInt32 gIndentSizeHeaders = 2; /* Indention of h1, if
mHeaderStrategy = 1 or = 2.
Indention of other headers
is derived from that.
XXX center h1? */
const PRInt32 gIndentIncrementHeaders = 2; /* If mHeaderStrategy = 1,
indent h(x+1) this many
columns more than h(x) */
const PRInt32 gIndentSizeList = (gTabSize > gOLNumberWidth+3) ? gTabSize: gOLNumberWidth+3;
// Indention of non-first lines of ul and ol
const PRInt32 gIndentSizeDD = gTabSize; // Indention of <dd>
static PRBool IsInline(eHTMLTags aTag);
static PRBool IsBlockLevel(eHTMLTags aTag);
static PRInt32 HeaderLevel(eHTMLTags aTag);
static PRInt32 unicharwidth(PRUnichar ucs);
static PRInt32 unicharwidth(const PRUnichar* pwcs, PRInt32 n);
@@ -181,6 +195,10 @@ nsHTMLToTXTSinkStream::nsHTMLToTXTSinkStream()
mBufferLength = 0;
mBuffer = nsnull;
mUnicodeEncoder = nsnull;
mStructs = PR_TRUE; // will be read from prefs later
mHeaderStrategy = 1 /*indent increasingly*/; // ditto
for (PRInt32 i = 0; i <= 6; i++)
mHeaderCounter[i] = 0;
// Line breaker
mLineBreaker = nsnull;
@@ -273,6 +291,15 @@ nsHTMLToTXTSinkStream::Initialize(nsIOutputStream* aOutStream,
else
mLineBreak.AssignWithConversion(NS_LINEBREAK); // Platform/default
// Get some prefs
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
if (NS_SUCCEEDED(rv) && prefs)
{
rv = prefs->GetBoolPref(PREF_STRUCTS, &mStructs);
rv = prefs->GetIntPref(PREF_HEADER_STRATEGY, &mHeaderStrategy);
}
return result;
}
@@ -514,7 +541,6 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
PRInt32 whitespace;
if(NS_SUCCEEDED(GetValueOfAttribute(aNode, "style", style)) &&
(-1 != (whitespace = style.Find("white-space:"))))
/* DELETEME: What, if the style is defined in an external stylesheet? */
{
if (-1 != style.Find("-moz-pre-wrap", PR_TRUE, whitespace))
{
@@ -569,19 +595,51 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
if (type == eHTMLTag_p || type == eHTMLTag_pre)
EnsureVerticalSpace(1); // Should this be 0 in unformatted case?
// Else make sure we'll separate block level tags,
// even if we're about to leave before doing any other formatting.
// Oddly, I can't find a case where this actually makes any difference.
//else if (IsBlockLevel(type))
// EnsureVerticalSpace(0);
// even if we're about to leave, before doing any other formatting.
else if (IsBlockLevel(type))
EnsureVerticalSpace(0);
// The rest of this routine is formatted output stuff,
// which we should skip if we're not formatted:
if (!(mFlags & nsIDocumentEncoder::OutputFormatted))
return NS_OK;
if (type == eHTMLTag_ul)
if (type == eHTMLTag_h1 || type == eHTMLTag_h2 ||
type == eHTMLTag_h3 || type == eHTMLTag_h4 ||
type == eHTMLTag_h5 || type == eHTMLTag_h6)
{
EnsureVerticalSpace(2);
if (mHeaderStrategy == 2) // numbered
{
mIndent += gIndentSizeHeaders;
// Caching
nsCAutoString leadup;
PRInt32 level = HeaderLevel(type);
// Increase counter for current level
mHeaderCounter[level]++;
// Reset all lower levels
PRInt32 i;
for (i = level + 1; i <= 6; i++)
mHeaderCounter[i] = 0;
// Construct numbers
for (i = 1; i <= level; i++)
{
leadup.AppendInt(mHeaderCounter[i]);
leadup += ".";
}
leadup += " ";
Write(NS_ConvertASCIItoUCS2(leadup.GetBuffer()));
}
else if (mHeaderStrategy == 1) // indent increasingly
{
mIndent += gIndentSizeHeaders;
for (PRInt32 i = HeaderLevel(type); i > 1; i--)
// for h(x), run x-1 times
mIndent += gIndentIncrementHeaders;
}
}
else if (type == eHTMLTag_ul)
{
// Indent here to support nested list, which aren't included in li :-(
EnsureVerticalSpace(1); // Must end the current line before we change indent.
@@ -612,7 +670,11 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
mInIndentString.AppendWithConversion(' ');
}
else if (type == eHTMLTag_td)
else if (type == eHTMLTag_dl)
EnsureVerticalSpace(1);
else if (type == eHTMLTag_dd)
mIndent += gIndentSizeDD;
else if (type == eHTMLTag_td || type == eHTMLTag_th)
{
// We must make sure that the content of two table cells get a
// space between them.
@@ -653,30 +715,39 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
}
else if (type == eHTMLTag_img)
{
nsAutoString url;
if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "src", url)) && !url.IsEmpty())
/* Output (in decreasing order of preference)
alt, title or src (URI) attribute */
// See <http://www.w3.org/TR/REC-html40/struct/objects.html#edef-IMG>
nsAutoString desc, temp;
if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "alt", desc)))
{
nsAutoString temp, desc;
if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "alt", desc))
&& !desc.IsEmpty())
if (!desc.IsEmpty())
{
temp.AppendWithConversion(" (");
temp.AppendWithConversion(" ["); // Should we output chars at all here?
desc.StripChars("\"");
temp += desc;
temp.AppendWithConversion(" <");
url.StripChars("\"");
temp += url;
temp.AppendWithConversion(">) ");
temp.AppendWithConversion(" ]");
}
else
{
temp.AppendWithConversion(" <");
url.StripChars("\"");
temp += url;
temp.AppendWithConversion("> ");
}
Write(temp);
// If the alt attribute has an empty value (|alt=""|), output nothing
}
else if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "title", desc))
&& !desc.IsEmpty())
{
temp.AppendWithConversion(" [");
desc.StripChars("\"");
temp += desc;
temp.AppendWithConversion("] ");
}
else if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "src", desc))
&& !desc.IsEmpty())
{
temp.AppendWithConversion(" <");
desc.StripChars("\"");
temp += desc;
temp.AppendWithConversion("> ");
}
if (!temp.IsEmpty())
Write(temp);
}
else if (type == eHTMLTag_a && !IsConverted(aNode))
{
@@ -688,15 +759,21 @@ nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode)
mURL = url;
}
}
else if (type == eHTMLTag_sup && !IsConverted(aNode))
else if (type == eHTMLTag_q)
Write(NS_ConvertASCIItoUCS2("\""));
else if (type == eHTMLTag_sup && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("^"));
else if (type == eHTMLTag_sub && !IsConverted(aNode))
else if (type == eHTMLTag_sub && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("_"));
else if ((type ==eHTMLTag_strong || type==eHTMLTag_b) && !IsConverted(aNode))
else if (type == eHTMLTag_code && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("|"));
else if ((type == eHTMLTag_strong || type == eHTMLTag_b)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("*"));
else if ((type == eHTMLTag_em || type == eHTMLTag_i) && !IsConverted(aNode))
else if ((type == eHTMLTag_em || type == eHTMLTag_i)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("/"));
else if (type == eHTMLTag_u && !IsConverted(aNode))
else if (type == eHTMLTag_u && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("_"));
return NS_OK;
@@ -729,6 +806,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
FlushLine();
} else if ((type == eHTMLTag_tr) ||
(type == eHTMLTag_li) ||
(type == eHTMLTag_dt) ||
(type == eHTMLTag_dd) ||
(type == eHTMLTag_pre) ||
(type == eHTMLTag_blockquote)) {
EnsureVerticalSpace(0);
@@ -737,7 +816,8 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
// in formatted mode, otherwise 0.
// This is hard. Sometimes 0 is a better number, but
// how to know?
EnsureVerticalSpace((mFlags & nsIDocumentEncoder::OutputFormatted) ? 1 : 0);
EnsureVerticalSpace((mFlags & nsIDocumentEncoder::OutputFormatted)
? 1 : 0);
}
}
@@ -746,7 +826,21 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
if (!(mFlags & nsIDocumentEncoder::OutputFormatted))
return NS_OK;
if (type == eHTMLTag_ul)
if (type == eHTMLTag_h1 || type == eHTMLTag_h2 ||
type == eHTMLTag_h3 || type == eHTMLTag_h4 ||
type == eHTMLTag_h5 || type == eHTMLTag_h6)
{
if (mHeaderStrategy /*numbered or indent increasingly*/ )
mIndent -= gIndentSizeHeaders;
if (mHeaderStrategy == 1 /*indent increasingly*/ )
{
for (PRInt32 i = HeaderLevel(type); i > 1; i--)
// for h(x), run x-1 times
mIndent -= gIndentIncrementHeaders;
}
EnsureVerticalSpace(1);
}
else if (type == eHTMLTag_ul)
{
mIndent -= gIndentSizeList;
}
@@ -756,12 +850,21 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
--mOLStackIndex;
mIndent -= gIndentSizeList;
}
else if (type == eHTMLTag_dd)
{
mIndent -= gIndentSizeDD;
}
else if (type == eHTMLTag_blockquote)
{
FlushLine();
if (mCiteQuoteLevel>0)
nsString value;
nsresult rv = GetValueOfAttribute(aNode, "type", value);
if ( NS_SUCCEEDED(rv) )
value.StripChars("\"");
if (NS_SUCCEEDED(rv) && value.EqualsWithConversion("cite", PR_TRUE))
mCiteQuoteLevel--;
else if(mIndent >= gTabSize)
else
mIndent -= gTabSize;
}
else if (type == eHTMLTag_a && !IsConverted(aNode) && !mURL.IsEmpty())
@@ -772,13 +875,20 @@ nsHTMLToTXTSinkStream::CloseContainer(const nsIParserNode& aNode)
Write(temp);
mURL.Truncate();
}
else if ((type== eHTMLTag_sup || type== eHTMLTag_sub) && !IsConverted(aNode))
else if (type == eHTMLTag_q)
Write(NS_ConvertASCIItoUCS2("\""));
else if ((type == eHTMLTag_sup || type == eHTMLTag_sub)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2(" "));
else if ((type== eHTMLTag_strong || type==eHTMLTag_b) && !IsConverted(aNode))
else if (type == eHTMLTag_code && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("|"));
else if ((type == eHTMLTag_strong || type == eHTMLTag_b)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("*"));
else if ((type == eHTMLTag_em || type == eHTMLTag_i) && !IsConverted(aNode))
else if ((type == eHTMLTag_em || type == eHTMLTag_i)
&& mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("/"));
else if (type == eHTMLTag_u && !IsConverted(aNode))
else if (type == eHTMLTag_u && mStructs && !IsConverted(aNode))
Write(NS_ConvertASCIItoUCS2("_"));
return NS_OK;
@@ -887,6 +997,7 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode)
EnsureVerticalSpace(0);
// Make a line of dashes as wide as the wrap width
// XXX honoring percentage would be nice
nsAutoString line;
PRUint32 width = (mWrapColumn > 0 ? mWrapColumn : 25);
while (line.Length() < width)
@@ -1483,20 +1594,23 @@ PRBool IsInline(eHTMLTags aTag)
{
case eHTMLTag_a:
case eHTMLTag_address:
case eHTMLTag_b:
case eHTMLTag_big:
case eHTMLTag_blink:
case eHTMLTag_b:
case eHTMLTag_br:
case eHTMLTag_cite:
case eHTMLTag_code:
case eHTMLTag_dfn:
case eHTMLTag_del:
case eHTMLTag_em:
case eHTMLTag_font:
case eHTMLTag_img:
case eHTMLTag_i:
case eHTMLTag_img:
case eHTMLTag_ins:
case eHTMLTag_kbd:
case eHTMLTag_keygen:
case eHTMLTag_nobr:
case eHTMLTag_q:
case eHTMLTag_samp:
case eHTMLTag_small:
case eHTMLTag_spacer:
@@ -1507,6 +1621,7 @@ PRBool IsInline(eHTMLTags aTag)
case eHTMLTag_sup:
case eHTMLTag_td:
case eHTMLTag_textarea:
case eHTMLTag_th:
case eHTMLTag_tt:
case eHTMLTag_u:
case eHTMLTag_var:
@@ -1523,6 +1638,36 @@ PRBool IsInline(eHTMLTags aTag)
PRBool IsBlockLevel(eHTMLTags aTag)
{
return !IsInline(aTag);
/* XXX Note: We output linebreaks for blocks.
I.e. we output linebreaks for "unknown" inline tags.
I just hunted such a bug for <q>, same for <ins>, <col> etc..
Better fallback to inline. /BenB */
}
/*
@return 0 = no header, 1 = h1, ..., 6 = h6
*/
PRInt32 HeaderLevel(eHTMLTags aTag)
{
PRInt32 result;
switch (aTag)
{
case eHTMLTag_h1:
result = 1; break;
case eHTMLTag_h2:
result = 2; break;
case eHTMLTag_h3:
result = 3; break;
case eHTMLTag_h4:
result = 4; break;
case eHTMLTag_h5:
result = 5; break;
case eHTMLTag_h6:
result = 6; break;
default:
result = 0; break;
}
return result;
}
PRBool nsHTMLToTXTSinkStream::MayWrap()

View File

@@ -189,6 +189,17 @@ protected:
PRBool mStartedOutput; // we've produced at least a character
nsString mURL;
PRInt32 mStructs; // Output structs (pref)
PRBool mHeaderStrategy; /* Header strategy (pref)
0 = no indention
1 = indention, increased with
header level (default)
2 = numbering and slight indention */
PRInt32 mHeaderCounter[7]; /* For header-numbering:
Number of previous headers of
the same depth and in the same
section.
mHeaderCounter[1] for <h1> etc. */
// The tag stack: the stack of tags we're operating on, so we can nest:
nsHTMLTag *mTagStack;

View File

@@ -1,5 +1,6 @@
Simple html page
Simple html page
Here is a link to the mozilla.org <http://www.mozilla.org> page. Here
is some _underlined and *bold*ened_ified text plus some <angle bracket
entities>.