in mailnews/compose/src/nsMsgCompose.cpp [4629:4796]
void nsMsgCompose::TagConvertible(Element* node, int32_t* _retval) {
*_retval = nsIMsgCompConvertible::No;
nsAutoString element;
element = node->NodeName();
// A style attribute on any element can change layout in any way,
// so that is not convertible.
nsAutoString attribValue;
node->GetAttribute(u"style"_ns, attribValue);
if (!attribValue.IsEmpty()) {
*_retval = nsIMsgCompConvertible::No;
return;
}
// moz-* classes are used internally by the editor and mail composition
// (like moz-cite-prefix or moz-signature). Those can be discarded.
// But any other ones are unconvertible. Style can be attached to them or any
// other context (e.g. in microformats).
node->GetAttribute(u"class"_ns, attribValue);
if (!attribValue.IsEmpty()) {
if (StringBeginsWith(attribValue, u"moz-"_ns,
nsCaseInsensitiveStringComparator)) {
// We assume that anything with a moz-* class is convertible regardless of
// the tag, because we add, for example, class="moz-signature" to HTML
// messages and we still want to be able to downgrade them.
*_retval = nsIMsgCompConvertible::Plain;
} else {
*_retval = nsIMsgCompConvertible::No;
}
return;
}
// ID attributes can contain attached style/context or be target of links
// so we should preserve them.
node->GetAttribute(u"id"_ns, attribValue);
if (!attribValue.IsEmpty()) {
*_retval = nsIMsgCompConvertible::No;
return;
}
// Alignment is not convertible to plaintext; editor currently uses this.
node->GetAttribute(u"align"_ns, attribValue);
if (!attribValue.IsEmpty()) {
*_retval = nsIMsgCompConvertible::No;
return;
}
// Title attribute is not convertible to plaintext;
// this also preserves any links with titles.
node->GetAttribute(u"title"_ns, attribValue);
if (!attribValue.IsEmpty()) {
*_retval = nsIMsgCompConvertible::No;
return;
}
// Treat <font face="monospace"> as converible to plaintext.
if (element.LowerCaseEqualsLiteral("font")) {
node->GetAttribute(u"size"_ns, attribValue);
if (!attribValue.IsEmpty()) {
*_retval = nsIMsgCompConvertible::No;
return;
}
node->GetAttribute(u"face"_ns, attribValue);
if (attribValue.LowerCaseEqualsLiteral("monospace")) {
*_retval = nsIMsgCompConvertible::Plain;
}
}
if ( // Considered convertible to plaintext: Some "simple" elements
// without non-convertible attributes like style, class, id,
// or align (see above).
element.LowerCaseEqualsLiteral("br") ||
element.LowerCaseEqualsLiteral("p") ||
element.LowerCaseEqualsLiteral("tt") ||
element.LowerCaseEqualsLiteral("html") ||
element.LowerCaseEqualsLiteral("head") ||
element.LowerCaseEqualsLiteral("meta") ||
element.LowerCaseEqualsLiteral("title")) {
*_retval = nsIMsgCompConvertible::Plain;
} else if (
// element.LowerCaseEqualsLiteral("blockquote") || // see below
element.LowerCaseEqualsLiteral("ul") ||
element.LowerCaseEqualsLiteral("ol") ||
element.LowerCaseEqualsLiteral("li") ||
element.LowerCaseEqualsLiteral("dl") ||
element.LowerCaseEqualsLiteral("dt") ||
element.LowerCaseEqualsLiteral("dd")) {
*_retval = nsIMsgCompConvertible::Yes;
} else if (
// element.LowerCaseEqualsLiteral("a") || // see below
element.LowerCaseEqualsLiteral("h1") ||
element.LowerCaseEqualsLiteral("h2") ||
element.LowerCaseEqualsLiteral("h3") ||
element.LowerCaseEqualsLiteral("h4") ||
element.LowerCaseEqualsLiteral("h5") ||
element.LowerCaseEqualsLiteral("h6") ||
element.LowerCaseEqualsLiteral("hr") ||
element.LowerCaseEqualsLiteral("pre") ||
(mConvertStructs && (element.LowerCaseEqualsLiteral("em") ||
element.LowerCaseEqualsLiteral("strong") ||
element.LowerCaseEqualsLiteral("code") ||
element.LowerCaseEqualsLiteral("b") ||
element.LowerCaseEqualsLiteral("i") ||
element.LowerCaseEqualsLiteral("u")))) {
*_retval = nsIMsgCompConvertible::Altering;
} else if (element.LowerCaseEqualsLiteral("body")) {
*_retval = nsIMsgCompConvertible::Plain;
if (node->HasAttribute(u"background"_ns) || // There is a background image
node->HasAttribute(
u"dir"_ns)) { // dir=rtl attributes should not downconvert
*_retval = nsIMsgCompConvertible::No;
} else {
nsAutoString color;
if (node->HasAttribute(u"text"_ns)) {
node->GetAttribute(u"text"_ns, color);
if (!color.EqualsLiteral("#000000"))
*_retval = nsIMsgCompConvertible::Altering;
}
if (*_retval != nsIMsgCompConvertible::Altering && // small optimization
node->HasAttribute(u"bgcolor"_ns)) {
node->GetAttribute(u"bgcolor"_ns, color);
if (!color.LowerCaseEqualsLiteral("#ffffff"))
*_retval = nsIMsgCompConvertible::Altering;
}
}
// ignore special color setting for link, vlink and alink at this point.
} else if (element.LowerCaseEqualsLiteral("blockquote")) {
// Skip <blockquote type="cite">
*_retval = nsIMsgCompConvertible::Yes;
node->GetAttribute(u"type"_ns, attribValue);
if (attribValue.LowerCaseEqualsLiteral("cite")) {
*_retval = nsIMsgCompConvertible::Plain;
}
} else if (element.LowerCaseEqualsLiteral("div") ||
element.LowerCaseEqualsLiteral("span") ||
element.LowerCaseEqualsLiteral("a")) {
// Do some special checks for these tags. They are inside this |else if|
// for performance reasons.
// Maybe, it's an <a> element inserted by another recognizer (e.g. 4.x')
if (element.LowerCaseEqualsLiteral("a")) {
// Ignore anchor tag, if the URI is the same as the text
// (as inserted by recognizers).
*_retval = nsIMsgCompConvertible::Altering;
nsAutoString hrefValue;
node->GetAttribute(u"href"_ns, hrefValue);
nsINodeList* children = node->ChildNodes();
if (children->Length() > 0) {
nsINode* pItem = children->Item(0);
nsAutoString textValue;
pItem->GetNodeValue(textValue);
if (textValue == hrefValue) *_retval = nsIMsgCompConvertible::Plain;
}
}
// Lastly, test, if it is just a "simple" <div> or <span>
else if (element.LowerCaseEqualsLiteral("div") ||
element.LowerCaseEqualsLiteral("span")) {
*_retval = nsIMsgCompConvertible::Plain;
}
}
}