Files
evolution/data/webkit/e-convert.js
Milan Crha fcd4768b2e EWebKitEditor: Switch to JavaScriptCore API
The C DOM API had been deprecated since WebKitGTK 2.22. This is
the editor rewrite to use the new API.
2020-04-27 15:06:56 +02:00

958 lines
24 KiB
JavaScript

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Copyright (C) 2019 Red Hat (www.redhat.com)
*
* This library is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
/* semi-convention: private functions start with lower-case letter,
public functions start with upper-case letter. */
var EvoConvert = {
MIN_PARAGRAPH_WIDTH : 5, // in characters
MIN_OL_WIDTH : 6, // includes ". " at the end
TAB_WIDTH : 8, // in characters
ALIGN_LEFT : 0,
ALIGN_CENTER : 1,
ALIGN_RIGHT : 2,
ALIGN_JUSTIFY : 3,
NOWRAP_CHAR_START : "\x01",
NOWRAP_CHAR_END : "\x02"
};
EvoConvert.GetOLMaxLetters = function(type, levels)
{
if (type && type.toUpperCase() == "I") {
if (levels < 2)
return 1;
if (levels < 3)
return 2;
if (levels < 8)
return 3;
if (levels < 18)
return 4;
if (levels < 28)
return 5;
if (levels < 38)
return 6;
if (levels < 88)
return 7
if (levels < 188)
return 8;
if (levels < 288)
return 9;
if (levels < 388)
return 10;
if (levels < 888)
return 11;
return 12;
} else if (type && type.toUpperCase() == "A") {
if (levels < 27)
return 1;
if (levels < 703)
return 2;
if (levels < 18279)
return 3;
return 4;
} else {
if (levels < 10)
return 1;
if (levels < 100)
return 2;
if (levels < 1000)
return 3;
if (levels < 10000)
return 4;
return 5;
}
}
EvoConvert.getOLIndexValue = function(type, value)
{
var str = "";
if (type == "A" || type == "a") { // alpha
var add = type.charCodeAt(0);
do {
str = String.fromCharCode(((value - 1) % 26) + add) + str;
value = Math.floor((value - 1) / 26);
} while (value);
} else if (type == "I" || type == "i") { // roman
var base = "IVXLCDM";
var b, r, add = 0;
if (value > 3999) {
str = "?";
} else {
if (type == "i")
base = base.toLowerCase();
for (b = 0; value > 0 && b < 7 - 1; b += 2, value = Math.floor(value / 10)) {
r = value % 10;
if (r != 0) {
if (r < 4) {
for (; r; r--)
str = String.fromCharCode(base.charCodeAt(b) + add) + str;
} else if (r == 4) {
str = String.fromCharCode(base.charCodeAt(b + 1) + add) + str;
str = String.fromCharCode(base.charCodeAt(b) + add) + str;
} else if (r == 5) {
str = String.fromCharCode(base.charCodeAt(b + 1) + add) + str;
} else if (r < 9) {
for (; r > 5; r--)
str = String.fromCharCode(base.charCodeAt(b) + add) + str;
str = String.fromCharCode(base.charCodeAt(b + 1) + add) + str;
} else if (r == 9) {
str = String.fromCharCode(base.charCodeAt(b + 2) + add) + str;
str = String.fromCharCode(base.charCodeAt(b) + add) + str;
}
}
}
}
} else { // numeric
str = "" + value;
}
return str;
}
EvoConvert.getComputedOrNodeStyle = function(node)
{
if (!node)
return null;
var parent = node;
while (parent && !(parent === document.body)) {
parent = parent.parentElement;
}
if (parent)
return window.getComputedStyle(node);
return node.style;
}
EvoConvert.replaceList = function(element, tagName)
{
var ll, lists, type = null;
if (tagName == "OL")
type = "";
lists = element.getElementsByTagName(tagName);
for (ll = lists.length - 1; ll >= 0; ll--) {
var list;
list = lists.item(ll);
if (!list)
continue;
var style = EvoConvert.getComputedOrNodeStyle(list), ltr, ii, prefixSuffix, indent;
if (!style)
style = list.style;
ltr = !style || style.direction != "rtl";
if (type == null) {
var level = 0, parent = list;
for (parent = list.parentElement; parent; parent = parent.parentElement) {
if (parent.tagName == "UL" || parent.tagName == "OL")
level++;
}
switch (level % 3) {
default:
case 0:
prefixSuffix = " * ";
break;
case 1:
prefixSuffix = " - ";
break;
case 2:
prefixSuffix = " + ";
break;
}
indent = 3;
} else {
type = list.getAttribute("type");
if (!type)
type = "";
var nChildren = 0, child;
for (ii = 0; ii < list.children.length; ii++) {
child = list.children.item(ii);
if (child.tagName == "LI")
nChildren++;
}
prefixSuffix = ltr ? ". " : " .";
indent = EvoConvert.GetOLMaxLetters(type, nChildren) + prefixSuffix.length;
if (indent < EvoConvert.MIN_OL_WIDTH)
indent = EvoConvert.MIN_OL_WIDTH;
}
if (list.hasAttribute("x-evo-extra-indent")) {
var tmp = list.getAttribute("x-evo-extra-indent");
if (tmp) {
tmp = parseInt(tmp);
if (!Number.isInteger(tmp))
tmp = 0;
} else {
tmp = 0;
}
indent += tmp;
}
var liCount = 0;
for (ii = 0; ii < list.children.length; ii++) {
var child = list.children.item(ii), node;
if (!child)
continue;
// nested lists
if (child.tagName == "DIV" && child.hasAttribute("x-evo-extra-indent") && child.hasAttribute("x-evo-li-text")) {
node = child.cloneNode(true);
var tmp = child.getAttribute("x-evo-extra-indent");
if (tmp) {
tmp = parseInt(tmp);
if (!Number.isInteger(tmp))
tmp = 0;
} else {
tmp = 0;
}
node.setAttribute("x-evo-extra-indent", indent + tmp);
tmp = node.getAttribute("x-evo-li-text");
if (ltr)
tmp = " ".repeat(indent) + tmp;
else
tmp = tmp + " ".repeat(indent);
node.setAttribute("x-evo-li-text", tmp);
} else if (child.tagName == "LI") {
liCount++;
node = document.createElement("DIV");
if (list.style.width.endsWith("ch")) {
var width = parseInt(list.style.width.slice(0, -2));
if (Number.isInteger(width))
node.style.width = "" + width + "ch";
}
node.style.textAlign = list.style.testAlign;
node.style.direction = list.style.direction;
node.style.marginLeft = list.style.marginLeft;
node.style.marginRight = list.style.marginRight;
node.setAttribute("x-evo-extra-indent", indent);
node.innerText = child.innerText;
if (type == null) {
node.setAttribute("x-evo-li-text", prefixSuffix);
} else {
var prefix;
prefix = EvoConvert.getOLIndexValue(type, liCount);
while (prefix.length + 2 /* prefixSuffix.length */ < indent) {
prefix = ltr ? " " + prefix : prefix + " ";
}
node.setAttribute("x-evo-li-text", ltr ? prefix + prefixSuffix : prefixSuffix + prefix);
}
} else {
node = child.cloneNode(true);
if (node.tagName == "UL" || node.tagName == "OL") {
var tmp = child.getAttribute("x-evo-extra-indent");
if (tmp) {
tmp = parseInt(tmp);
if (!Number.isInteger(tmp))
tmp = 0;
} else {
tmp = 0;
}
node.setAttribute("x-evo-extra-indent", indent + tmp);
}
}
list.parentNode.insertBefore(node, list);
}
list.parentNode.removeChild(list);
}
}
EvoConvert.calcLineLetters = function(line)
{
var len;
if (line.search("\t") >= 0) {
var jj;
len = 0;
for (jj = 0; jj < line.length; jj++) {
if (line.charAt(jj) == "\t") {
len = len - (len % EvoConvert.TAB_SIZE) + EvoConvert.TAB_SIZE;
} else {
len++;
}
}
} else {
len = line.length;
}
return len;
}
EvoConvert.getQuotePrefix = function(quoteLevel, ltr)
{
var prefix = "";
if (quoteLevel > 0) {
prefix = ltr ? "> " : " <";
prefix = prefix.repeat(quoteLevel);
}
return prefix;
}
EvoConvert.formatParagraph = function(str, ltr, align, indent, whiteSpace, wrapWidth, extraIndent, liText, quoteLevel)
{
if (!str || str == "")
return liText ? liText : str;
var lines = [], ii;
// wrap the string first
if (wrapWidth > 0) {
var worker = {
collapseWhiteSpace : whiteSpace != "pre" && whiteSpace != "pre-wrap",
collapseEndingWhiteSpace : whiteSpace != "pre",
canWrap : whiteSpace != "nowrap",
charWrap : whiteSpace == "pre",
inAnchor : 0,
ignoreLineLetters : 0, // used for EvoConvert.NOWRAP_CHAR_START and EvoConvert.NOWRAP_CHAR_END, which should be skipped in width calculation
useWrapWidth : wrapWidth,
spacesFrom : -1, // in 'str'
lastSpace : -1, // in this->line
lineLetters : 0,
line : "",
maybeRecalcIgnoreLineLetters : function() {
if (this.ignoreLineLetters) {
var ii, len = this.line.length, chr;
this.ignoreLineLetters = 0;
for (ii = 0; ii < len; ii++) {
chr = this.line[ii];
if (chr == EvoConvert.NOWRAP_CHAR_START || chr == EvoConvert.NOWRAP_CHAR_END)
this.ignoreLineLetters++;
}
}
},
mayConsumeWhitespaceAfterWrap : function(str, ii) {
return ii > 0 && this.line == "" && str[ii - 1] == EvoConvert.NOWRAP_CHAR_END;
},
isInUnwrapPart : function() {
if (this.inAnchor)
return true;
if (this.line[0] == EvoConvert.NOWRAP_CHAR_START)
return this.line.indexOf(EvoConvert.NOWRAP_CHAR_END) < 0;
return false;
},
shouldWrap : function(nextChar) {
return this.canWrap && (!this.collapseWhiteSpace || nextChar != '\n') &&
(!this.isInUnwrapPart() || this.lastSpace != -1) && (this.lineLetters - this.ignoreLineLetters > this.useWrapWidth || (
((!this.charWrap && (nextChar == " " || nextChar == "\t") && this.lineLetters - this.ignoreLineLetters > this.useWrapWidth) ||
((this.charWrap || (nextChar != " " && nextChar != "\t")) && this.lineLetters - this.ignoreLineLetters == this.useWrapWidth)) && (
this.lastSpace == -1/* || this.lastSpace == this.line.length*/)));
},
commitSpaces : function(ii) {
if (this.spacesFrom != -1 && (!this.canWrap || this.line.length - this.ignoreLineLetters <= this.useWrapWidth)) {
var spaces;
spaces = ii - this.spacesFrom;
if (this.canWrap && this.line.length - this.ignoreLineLetters + spaces > this.useWrapWidth)
spaces = this.useWrapWidth - this.line.length + this.ignoreLineLetters;
if (!this.canWrap || (this.line.length - this.ignoreLineLetters + spaces <= this.useWrapWidth) && spaces >= 0) {
if (this.collapseWhiteSpace && (!extraIndent || lines.length))
this.line += " ";
else
this.line += " ".repeat(spaces);
}
this.spacesFrom = -1;
this.lastSpace = this.line.length;
} else if (this.spacesFrom != -1) {
this.lastSpace = this.line.length;
}
},
commit : function(ii, force) {
this.commitSpaces(ii);
var didWrap = false;
if (this.canWrap && this.lastSpace != -1 && this.lineLetters - this.ignoreLineLetters > this.useWrapWidth) {
lines[lines.length] = this.line.substr(0, this.lastSpace);
this.line = this.line.substr(this.lastSpace);
this.maybeRecalcIgnoreLineLetters();
didWrap = true;
} else if (!this.isInUnwrapPart() && this.useWrapWidth != -1 && this.lineLetters - this.ignoreLineLetters > this.useWrapWidth) {
var jj;
if (this.charWrap) {
var subLineLetters = 0, ignoreSubLineLetters = 0, chr;
for(jj = 0; jj < this.line.length; jj++) {
chr = this.line.charAt(jj);
if (chr == "\t") {
subLineLetters = subLineLetters - ((subLineLetters - ignoreSubLineLetters) % EvoConvert.TAB_SIZE) + EvoConvert.TAB_SIZE;
} else {
subLineLetters++;
}
if (chr == EvoConvert.NOWRAP_CHAR_START || chr == EvoConvert.NOWRAP_CHAR_END)
ignoreSubLineLetters++;
if (subLineLetters - ignoreSubLineLetters >= this.useWrapWidth)
break;
}
} else {
jj = this.line.length;
}
lines[lines.length] = this.line.substr(0, jj);
this.line = this.line.substr(jj);
this.maybeRecalcIgnoreLineLetters();
didWrap = true;
} else {
lines[lines.length] = this.line;
this.line = "";
this.ignoreLineLetters = 0;
}
if (this.canWrap && this.collapseEndingWhiteSpace && didWrap && lines[lines.length - 1].endsWith(" ")) {
if (lines[lines.length - 1].length == 1)
lines.length = lines.length - 1;
else
lines[lines.length - 1] = lines[lines.length - 1].substr(0, lines[lines.length - 1].length - 1);
}
if (force && this.line) {
lines[lines.length] = this.line;
this.line = "";
this.ignoreLineLetters = 0;
}
this.lineLetters = this.canWrap ? EvoConvert.calcLineLetters(this.line) : this.line.length;
this.spacesFrom = -1;
this.lastSpace = -1;
}
};
if (worker.useWrapWidth < EvoConvert.MIN_PARAGRAPH_WIDTH)
worker.useWrapWidth = EvoConvert.MIN_PARAGRAPH_WIDTH;
var chr;
for (ii = 0; ii < str.length; ii++) {
chr = str.charAt(ii);
if (chr == EvoConvert.NOWRAP_CHAR_START)
worker.inAnchor++;
if (chr == "\n") {
if (!worker.mayConsumeWhitespaceAfterWrap(str, ii))
worker.commit(ii, true);
} else if (!worker.charWrap && !worker.collapseWhiteSpace && chr == "\t") {
if (worker.shouldWrap(str[ii + 1]))
worker.commit(ii, false);
else
worker.commitSpaces(ii);
var add = chr; // this expands the tab, instead of leaving it '\t'... " ".repeat(EvoConvert.TAB_WIDTH - ((worker.lineLetters - worker.ignoreLineLetters) % EvoConvert.TAB_WIDTH));
worker.lineLetters = worker.lineLetters - ((worker.lineLetters - worker.ignoreLineLetters) % EvoConvert.TAB_WIDTH) + EvoConvert.TAB_WIDTH;
if (worker.shouldWrap(str[ii + 1]))
worker.commit(ii, false);
worker.line += add;
worker.lineLetters += add.length;
} else if (!worker.charWrap && (chr == " " || chr == "\t")) {
var setSpacesFrom = false;
if (chr == '\t') {
worker.lineLetters = worker.lineLetters - ((worker.lineLetters - worker.ignoreLineLetters) % EvoConvert.TAB_WIDTH) + EvoConvert.TAB_WIDTH;
setSpacesFrom = true;
} else if ((worker.spacesFrom == -1 && worker.line != "") || (!worker.collapseWhiteSpace && !worker.mayConsumeWhitespaceAfterWrap(str, ii))) {
worker.lineLetters++;
setSpacesFrom = true;
}
// all spaces at the end of paragraph line are ignored
if (setSpacesFrom && worker.spacesFrom == -1)
worker.spacesFrom = ii;
} else {
worker.commitSpaces(ii);
worker.line += chr;
if (chr == "\t")
worker.lineLetters = worker.lineLetters - ((worker.lineLetters - worker.ignoreLineLetters) % EvoConvert.TAB_WIDTH) + EvoConvert.TAB_WIDTH;
else
worker.lineLetters++;
if (chr == EvoConvert.NOWRAP_CHAR_START || chr == EvoConvert.NOWRAP_CHAR_END)
worker.ignoreLineLetters++;
if (chr == EvoConvert.NOWRAP_CHAR_END && worker.inAnchor)
worker.inAnchor--;
if (worker.shouldWrap(str[ii + 1]))
worker.commit(ii, false);
}
}
while (worker.line.length || worker.spacesFrom != -1 || !lines.length) {
worker.commit(ii, false);
}
} else {
if (str.endsWith("\n"))
str = str.substr(0, str.length - 1);
lines = str.split("\n");
}
var extraIndentStr = extraIndent > 0 ? " ".repeat(extraIndent) : null;
if (wrapWidth <= 0) {
for (ii = 0; ii < lines.length; ii++) {
var len = EvoConvert.calcLineLetters(lines[ii]);
if (wrapWidth < len)
wrapWidth = len;
}
}
str = "";
for (ii = 0; ii < lines.length; ii++) {
var line = lines[ii];
if ((!ltr && align == EvoConvert.ALIGN_LEFT) ||
(ltr && align == EvoConvert.ALIGN_RIGHT)) {
var len = EvoConvert.calcLineLetters(line);
if (len < wrapWidth) {
var add = " ".repeat(wrapWidth - len);
if (ltr)
line = add + line;
else
line = line + add;
}
} else if (align == EvoConvert.ALIGN_CENTER) {
var len = EvoConvert.calcLineLetters(line);
if (len < wrapWidth) {
var add = " ".repeat((wrapWidth - len) / 2);
if (ltr)
line = add + line;
else
line = line + add;
}
} else if (align == EvoConvert.ALIGN_JUSTIFY && ii + 1 < lines.length) {
var len = EvoConvert.calcLineLetters(line);
if (len < wrapWidth) {
var words = line.split(" ");
if (words.length > 1) {
var nAdd = (wrapWidth - len);
var add = " ".repeat(nAdd / (words.length - 1) >= 1 ? nAdd / (words.length - 1) : nAdd), jj;
for (jj = 0; jj < words.length - 1 && nAdd > 0; jj++) {
words[jj] = words[jj] + add;
nAdd -= add.length;
if (nAdd > 0 && jj + 2 >= words.length) {
words[jj] = " ".repeat(nAdd) + words[jj];
}
}
line = words[0];
for (jj = 1; jj < words.length; jj++) {
line = line + " " + words[jj];
}
}
}
}
if (!ii && liText) {
if (ltr)
line = liText + line;
else
line = line + liText;
} else if (extraIndentStr && ii > 0) {
if (ltr)
line = extraIndentStr + line;
else
line = line + extraIndentStr;
}
if (indent != "") {
if (ltr && align != EvoConvert.ALIGN_RIGHT)
line = indent + line;
else
line = line + indent;
}
if (quoteLevel > 0) {
if (ltr)
line = EvoConvert.getQuotePrefix(quoteLevel, ltr) + line;
else
line = line + EvoConvert.getQuotePrefix(quoteLevel, ltr);
}
str += line + "\n";
}
return str;
}
EvoConvert.ImgToText = function(img)
{
if (!img)
return "";
var txt;
txt = img.alt;
return txt ? txt : "";
}
EvoConvert.extractElemText = function(elem, normalDivWidth, quoteLevel)
{
if (!elem)
return "";
if (!elem.childNodes.length)
return elem.innerText;
var str = "", ii;
for (ii = 0; ii < elem.childNodes.length; ii++) {
var node = elem.childNodes.item(ii);
if (!node)
continue;
str += EvoConvert.processNode(node, normalDivWidth, quoteLevel);
}
return str;
}
EvoConvert.mergeConsecutiveSpaces = function(str)
{
if (str.indexOf(" ") >= 0) {
var words = str.split(" "), ii, word;
str = "";
for (ii = 0; ii < words.length; ii++) {
word = words[ii];
if (word) {
if (ii)
str += " ";
str += word;
}
}
if (!words[words.length - 1])
str += " ";
}
return str;
}
EvoConvert.processNode = function(node, normalDivWidth, quoteLevel)
{
var str = "";
if (node.nodeType == node.TEXT_NODE) {
str = node.nodeValue;
if (str.indexOf("\r") >= 0 ||
str.indexOf("\n") >= 0 ||
str.indexOf("\t") >= 0 ||
str.indexOf(" ") >= 0) {
var whiteSpace = "normal";
if (node.parentElement)
whiteSpace = window.getComputedStyle(node.parentElement).whiteSpace;
if (whiteSpace == "pre-line") {
str = EvoConvert.mergeConsecutiveSpaces(str.replace(/\t/g, " "));
} else if (!whiteSpace || whiteSpace == "normal" || whiteSpace == "nowrap") {
if (str == "\n" || str == "\r" || str == "\r\n") {
str = "";
} else {
if ((!node.previousSibling || node.previousSibling.tagName) && (str[0] == '\r' || str[0] == '\n')) {
var ii;
for (ii = 0; str[ii] == '\n' || str[ii] == '\r'; ii++) {
// do nothing, just skip all leading insignificant new lines
}
str = str.substr(ii);
}
if (str.length > 0 && (!node.nextSibling || node.nextSibling.tagName) && (str[str.length - 1] == '\r' || str[str.length - 1] == '\n')) {
var ii;
for (ii = str.length - 1; ii >= 0 && (str[ii] == '\n' || str[ii] == '\r'); ii--) {
// do nothing, just skip all trailing insignificant new lines
}
str = str.substr(0, ii + 1);
}
str = EvoConvert.mergeConsecutiveSpaces(str.replace(/\t/g, " ").replace(/\r/g, " ").replace(/\n/g, " "));
}
}
}
} else if (node.nodeType == node.ELEMENT_NODE) {
if (node.hidden ||
node.tagName == "STYLE" ||
node.tagName == "META" ||
(node.tagName == "SPAN" && node.classList.contains("-x-evo-quoted")))
return str;
var style = EvoConvert.getComputedOrNodeStyle(node), ltr, align, indent, whiteSpace;
if (!style)
style = node.style;
ltr = !style || style.direction != "rtl";
align = style ? style.textAlign : "";
if (!align || align == "")
align = node.style.textAlign;
if (align)
align = align.toLowerCase();
if (!align)
align = "";
if (align == "" || align == "start")
align = ltr ? "left" : "right";
if (align == "center")
align = EvoConvert.ALIGN_CENTER;
else if (align == "right")
align = EvoConvert.ALIGN_RIGHT;
else if (align == "justify")
align = EvoConvert.ALIGN_JUSTIFY;
else
align = EvoConvert.ALIGN_LEFT;
// mixed indent and opposite text align does nothing
if ((ltr && align == EvoConvert.ALIGN_RIGHT) ||
(!ltr && align == EvoConvert.ALIGN_LEFT)) {
indent = "";
} else {
// computed style's 'indent' uses pixels, not characters
indent = ltr ? node.style.marginLeft : node.style.marginRight;
}
if (indent && indent.endsWith("ch")) {
indent = parseInt(indent.slice(0, -2));
if (!Number.isInteger(indent) || indent < 0)
indent = 0;
} else {
indent = 0;
}
if (indent > 0)
indent = " ".repeat(indent);
else
indent = "";
whiteSpace = style ? style.whiteSpace.toLowerCase() : "";
if (node.tagName == "DIV" || node.tagName == "P") {
var liText, extraIndent, width, useDefaultWidth = false;
liText = node.getAttribute("x-evo-li-text");
if (!liText)
liText = "";
extraIndent = node.getAttribute("x-evo-extra-indent");
extraIndent = extraIndent ? parseInt(extraIndent, 10) : 0;
if (!Number.isInteger(extraIndent)) {
extraIndent = 0;
}
width = node.style.width;
if (width && width.endsWith("ch")) {
width = parseInt(width.slice(0, -2));
if (!Number.isInteger(width) || width < 0)
useDefaultWidth = true;
} else {
useDefaultWidth = true;
}
if (useDefaultWidth && normalDivWidth > 0) {
width = normalDivWidth - (quoteLevel * 2);
if (width < EvoConvert.MIN_PARAGRAPH_WIDTH)
width = EvoConvert.MIN_PARAGRAPH_WIDTH;
}
str = EvoConvert.formatParagraph(EvoConvert.extractElemText(node, normalDivWidth, quoteLevel), ltr, align, indent, whiteSpace, width, extraIndent, liText, quoteLevel);
} else if (node.tagName == "PRE") {
str = EvoConvert.formatParagraph(EvoConvert.extractElemText(node, normalDivWidth, quoteLevel), ltr, align, indent, "pre", -1, 0, "", quoteLevel);
} else if (node.tagName == "BR") {
// ignore new-lines added by wrapping, treat them as spaces
if (node.classList.contains("-x-evo-wrap-br"))
str += " ";
else
str = "\n";
} else if (node.tagName == "IMG") {
str = EvoConvert.ImgToText(node);
} else if (node.tagName == "A" && !node.innerText.includes(" ") && !node.innerText.includes("\n")) {
str = EvoConvert.NOWRAP_CHAR_START + node.innerText + EvoConvert.NOWRAP_CHAR_END;
} else {
var isBlockquote = node.tagName == "BLOCKQUOTE";
str = EvoConvert.extractElemText(node, normalDivWidth, quoteLevel + (isBlockquote ? 1 : 0));
if ((!isBlockquote || !str.endsWith("\n")) &&
str != "\n" && ((style && style.display == "block") || node.tagName == "ADDRESS")) {
str += "\n";
}
}
}
return str;
}
/*
* Converts element and its children to plain text. Any <div>,<ul>,<ol>, as an immediate child
* of the element, is wrapped to upto normalDivWidth characters, if it's defined and greater
* than EvoConvert.MIN_PARAGRAPH_WIDTH.
*/
EvoConvert.ToPlainText = function(element, normalDivWidth)
{
if (!element)
return null;
if (element.tagName == "HTML") {
var bodys;
bodys = element.getElementsByTagName("BODY");
if (bodys.length == 1)
element = bodys.item(0);
}
if (!element)
return null;
if (!normalDivWidth)
normalDivWidth = -1;
var disconnectFromHead = false;
if (!element.isConnected) {
// this is needed to be able to use window.getComputedStyle()
document.head.appendChild(element);
disconnectFromHead = true;
}
try {
var uls, ols, str = "", ii;
uls = element.getElementsByTagName("UL");
ols = element.getElementsByTagName("OL");
if (uls.length > 0 || ols.length > 0) {
element = element.cloneNode(true);
if (uls.length)
EvoConvert.replaceList(element, "UL");
if (ols.length)
EvoConvert.replaceList(element, "OL");
}
for (ii = 0; ii < element.childNodes.length; ii++) {
var node = element.childNodes.item(ii);
if (!node)
continue;
str += EvoConvert.processNode(node, normalDivWidth, 0);
}
} finally {
if (disconnectFromHead)
document.head.removeChild(element);
}
// remove EvoConvert.NOWRAP_CHAR_START and EvoConvert.NOWRAP_CHAR_END from the result
return str.replace(/\x01/g, "").replace(/\x02/g, "");
}