[evolution/wip/mcrha/webkit-jsc-api] Extend e-convert.js to cover paragraph formats and such, with added tests



commit 1f136b5f7e49b572a39c4777fc375d66a8be5f16
Author: Milan Crha <mcrha redhat com>
Date:   Wed Nov 20 18:03:40 2019 +0100

    Extend e-convert.js to cover paragraph formats and such, with added tests

 data/webkit/e-convert.js       | 661 ++++++++++++++++++++++++++++++++++++++++-
 data/webkit/e-editor.js        |  82 ++++-
 data/webkit/e-web-view.js      |   4 +-
 src/e-util/test-web-view-jsc.c | 620 +++++++++++++++++++++++++++++++++++++-
 4 files changed, 1354 insertions(+), 13 deletions(-)
---
diff --git a/data/webkit/e-convert.js b/data/webkit/e-convert.js
index 8fa7c0f37f..7ddcdee99f 100644
--- a/data/webkit/e-convert.js
+++ b/data/webkit/e-convert.js
@@ -20,10 +20,667 @@
 /* semi-convention: private functions start with lower-case letter,
    public functions start with upper-case letter. */
 
-function EvoConvertToPlainText(element)
+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
+};
+
+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++;
+                       }
+
+                       if (!(level % 2))
+                               prefixSuffix = " * ";
+                       else
+                               prefixSuffix = " # ";
+
+                       indent = 3;
+               } else {
+                       type = list.getAttribute("type");
+
+                       if (!type)
+                               type = "";
+
+                       prefixSuffix = ltr ? ". " : " .";
+                       indent = EvoConvert.GetOLMaxLetters(type, list.children.length) + prefixSuffix.length;
+                       if (indent < EvoConvert.MIN_OL_WIDTH)
+                               indent = EvoConvert.MIN_OL_WIDTH;
+               }
+
+               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);
+                       }
+
+                       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.formatParagraph = function(str, ltr, align, indent, whiteSpace, wrapWidth, extraIndent, liText)
+{
+       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",
+                       canWrap : whiteSpace != "nowrap",
+                       charWrap : whiteSpace == "pre",
+                       useWrapWidth : wrapWidth,
+                       spacesFrom : -1, // in 'str'
+                       lastSpace : -1, // in this->line
+                       lineLetters : 0,
+                       line : "",
+
+                       shouldWrap : function() {
+                               return worker.canWrap && (worker.lineLetters > worker.useWrapWidth || (
+                                       worker.lineLetters == worker.useWrapWidth && worker.lastSpace == -1));
+                       },
+
+                       commitSpaces : function(ii) {
+                               if (worker.spacesFrom != -1 && (!worker.canWrap || worker.line.length <= 
worker.useWrapWidth)) {
+                                       var spaces;
+
+                                       spaces = ii - worker.spacesFrom;
+
+                                       if (worker.canWrap && worker.line.length + spaces > 
worker.useWrapWidth)
+                                               spaces = worker.useWrapWidth - worker.line.length;
+
+                                       if (!worker.canWrap || (worker.line.length + spaces <= 
worker.useWrapWidth) && spaces >= 0) {
+                                               if (worker.collapseWhiteSpace && (!extraIndent || 
lines.length))
+                                                       worker.line += " ";
+                                               else
+                                                       worker.line += " ".repeat(spaces);
+                                       }
+
+                                       worker.spacesFrom = -1;
+                                       worker.lastSpace = worker.line.length;
+                               } else if (worker.spacesFrom != -1) {
+                                       worker.lastSpace = worker.line.length;
+                               }
+                       },
+
+                       commit : function(ii) {
+                               worker.commitSpaces(ii);
+
+                               if (worker.canWrap && worker.lastSpace != -1 && worker.lineLetters > 
worker.useWrapWidth) {
+                                       lines[lines.length] = worker.line.substr(0, worker.lastSpace);
+                                       worker.line = worker.line.substr(worker.lastSpace);
+                               } else if (worker.charWrap && worker.useWrapWidth != -1 && worker.lineLetters 
worker.useWrapWidth) {
+                                       var jj, subLineLetters = 0;
+
+                                       for(jj = 0; jj < worker.line.length; jj++) {
+                                               if (worker.line.charAt(jj) == "\t") {
+                                                       subLineLetters = subLineLetters - (subLineLetters % 
EvoConvert.TAB_SIZE) + EvoConvert.TAB_SIZE;
+                                               } else {
+                                                       subLineLetters++;
+                                               }
+
+                                               if (subLineLetters >= worker.useWrapWidth)
+                                                       break;
+                                       }
+
+                                       lines[lines.length] = worker.line.substr(0, jj);
+                                       worker.line = worker.line.substr(jj);
+                               } else {
+                                       lines[lines.length] = worker.line;
+                                       worker.line = "";
+                               }
+
+                               if (worker.canWrap && worker.collapseWhiteSpace && lines[lines.length - 
1].endsWith(" ")) {
+                                       lines[lines.length - 1] = lines[lines.length - 1].substr(0, 
lines[lines.length - 1].length - 1);
+                               }
+
+                               worker.lineLetters = worker.canWrap ? EvoConvert.calcLineLetters(worker.line) 
: worker.line.length;
+                               worker.spacesFrom = -1;
+                               worker.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 == "\r")
+                               continue;
+
+                       if (chr == "\n") {
+                               worker.commit(ii);
+                       } else if (!worker.charWrap && !worker.collapseWhiteSpace && chr == "\t") {
+                               if (worker.shouldWrap())
+                                       worker.commit(ii);
+                               else
+                                       worker.commitSpaces(ii);
+
+                               var add = " ".repeat(EvoConvert.TAB_WIDTH - (worker.lineLetters % 
EvoConvert.TAB_WIDTH));
+
+                               worker.lineLetters = worker.lineLetters - (worker.lineLetters % 
EvoConvert.TAB_WIDTH) + EvoConvert.TAB_WIDTH;
+
+                               if (worker.shouldWrap())
+                                       worker.commit(ii);
+
+                               worker.line += add;
+                               worker.lineLetters += add.length;
+                       } else if (!worker.charWrap && (chr == " " || chr == "\t")) {
+                               if (chr == '\t')
+                                       worker.lineLetters = worker.lineLetters - (worker.lineLetters % 
EvoConvert.TAB_WIDTH) + EvoConvert.TAB_WIDTH;
+                               else if (worker.spacesFrom == -1 || !worker.collapseWhiteSpace)
+                                       worker.lineLetters++;
+
+                               // all spaces at the end of paragraph line are ignored
+                               if (worker.spacesFrom == -1)
+                                       worker.spacesFrom = ii;
+                       } else {
+                               worker.commitSpaces(ii);
+                               worker.line += chr;
+
+                               if (chr == "\t")
+                                       worker.lineLetters = worker.lineLetters - (worker.lineLetters % 
EvoConvert.TAB_WIDTH) + EvoConvert.TAB_WIDTH;
+                               else
+                                       worker.lineLetters++;
+
+                               if (worker.shouldWrap())
+                                       worker.commit(ii);
+                       }
+               }
+
+               while (worker.line.length || worker.spacesFrom != -1 || !lines.length) {
+                       worker.commit(ii);
+               }
+       } else {
+               lines[lines.length] = str;
+       }
+
+       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;
+               }
+
+               str += line + "\n";
+       }
+
+       return str;
+}
+
+EvoConvert.processNode = function(node, normalDivWidth)
+{
+       var str = "";
+
+       if (node.nodeType == node.TEXT_NODE) {
+               str = node.nodeValue;
+       } else if (node.nodeType == node.ELEMENT_NODE) {
+               if (node.hidden)
+                       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") {
+                       var liText, extraIndent, width;
+
+                       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)
+                                       width = normalDivWidth;
+                       } else {
+                               width = normalDivWidth;
+                       }
+
+                       str = EvoConvert.formatParagraph(node.innerText, ltr, align, indent, whiteSpace, 
width, extraIndent, liText);
+               } else if (node.tagName == "PRE") {
+                       str = EvoConvert.formatParagraph(node.innerText, ltr, align, indent, "pre", -1, 0, 
"");
+               } else if (node.tagName == "BR") {
+                       str = "\n";
+               } else {
+                       str = node.innerText;
+
+                       if (style && style.display == "block") {
+                               str += "\n";
+
+                               if (node.tagName == "H1" ||
+                                   node.tagName == "H2" ||
+                                   node.tagName == "H3" ||
+                                   node.tagName == "H4" ||
+                                   node.tagName == "H5" ||
+                                   node.tagName == "H6")
+                                       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;
 
-       return element.innerText;
+       if (!normalDivWidth)
+               normalDivWidth = -1;
+
+       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);
+       }
+
+       return str;
 }
diff --git a/data/webkit/e-editor.js b/data/webkit/e-editor.js
index 8cf407a603..b1a342fa14 100644
--- a/data/webkit/e-editor.js
+++ b/data/webkit/e-editor.js
@@ -56,6 +56,7 @@ var EvoEditor = {
        CLAIM_CONTENT_FLAG_SAVE_HTML : 1 << 1,
 
        TEXT_INDENT_SIZE : 3, // in characters
+       NORMAL_PARAGRAPH_WIDTH : 71,
 
        FORCE_NO : 0,
        FORCE_YES : 1,
@@ -1205,6 +1206,78 @@ EvoEditor.initializeContent = function()
        }
 }
 
+EvoEditor.convertParagraphs = function(parent, wrapWidth)
+{
+       if (!parent)
+               return;
+
+       var ii;
+
+       for (ii = 0; ii < parent.children.length; ii++) {
+               var child = parent.children.item(ii);
+
+               if (child.tagName == "DIV") {
+                       if (wrapWidth == -1) {
+                               child.style.width = "";
+                       } else {
+                               child.style.width = wrapWidth + "ch";
+                       }
+               } else if (child.tagName == "BLOCKQUOTE") {
+                       var innerWrapWidth = wrapWidth;
+
+                       innerWrapWidth -= 2; // length of "> "
+
+                       if (innerWrapWidth < EvoConvert.MIN_PARAGRAPH_WIDTH)
+                               innerWrapWidth = EvoConvert.MIN_PARAGRAPH_WIDTH;
+
+                       EvoEditor.convertParagraphs(child, innerWrapWidth);
+               } else if (child.tagName == "UL") {
+                       if (wrapWidth == -1) {
+                               child.style.width = "";
+                       } else {
+                               var innerWrapWidth = wrapWidth;
+
+                               innerWrapWidth -= 3; // length of " * " prefix
+
+                               if (innerWrapWidth < EvoConvert.MIN_PARAGRAPH_WIDTH)
+                                       innerWrapWidth = EvoConvert.MIN_PARAGRAPH_WIDTH;
+
+                               child.style.width = innerWrapWidth + "ch";
+                       }
+               } else if (child.tagName == "OL") {
+                       if (wrapWidth == -1) {
+                               child.style.width = "";
+                               child.style.paddingInlineStart = "";
+                       } else {
+                               var innerWrapWidth = wrapWidth, olNeedWidth;
+
+                               olNeedWidth = EvoEditor.GetOLMaxLetters(child.getAttribute("type"), 
child.children.length) + 2; // length of ". " suffix
+
+                               if (olNeedWidth < EvoConvert.MIN_OL_WIDTH)
+                                       olNeedWidth = EvoConvert.MIN_OL_WIDTH;
+
+                               innerWrapWidth -= olNeedWidth;
+
+                               if (innerWrapWidth < EvoConvert.MIN_PARAGRAPH_WIDTH)
+                                       innerWrapWidth = EvoConvert.MIN_PARAGRAPH_WIDTH;
+
+                               child.style.width = innerWrapWidth + "ch";
+                               child.style.paddingInlineStart = olNeedWidth + "ch";
+                       }
+               }
+       }
+}
+
+EvoEditor.SetNormalParagraphWidth = function(value)
+{
+       if (EvoEditor.NORMAL_PARAGRAPH_WIDTH != value) {
+               EvoEditor.NORMAL_PARAGRAPH_WIDTH = value;
+
+               if (EvoEditor.mode == EvoEditor.MODE_PLAIN_TEXT)
+                       EvoEditor.convertParagraphs(document.body, EvoEditor.NORMAL_PARAGRAPH_WIDTH);
+       }
+}
+
 EvoEditor.SetMode = function(mode)
 {
        if (EvoEditor.mode != mode) {
@@ -1224,19 +1297,18 @@ EvoEditor.SetMode = function(mode)
                        }
                }
 
-               EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_DOCUMENT, opType);
-
                EvoUndoRedo.Disable();
                try {
                        EvoEditor.mode = mode;
 
                        if (mode == EvoEditor.MODE_PLAIN_TEXT) {
-                               // TODO convert HTML to "rich" plain-text
+                               EvoEditor.convertParagraphs(document.body, EvoEditor.NORMAL_PARAGRAPH_WIDTH);
                        } else {
-                               // TODO convert plain to HTML
+                               EvoEditor.convertParagraphs(document.body, -1);
                        }
                } finally {
                        EvoUndoRedo.Enable();
+                       EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_DOCUMENT, opType);
                }
        }
 }
@@ -1356,7 +1428,7 @@ EvoEditor.GetContent = function(flags, cid_uid_prefix)
                        content_data["to-send-html"] = EvoEditor.convertHtmlToSend();
 
                if ((flags & EvoEditor. E_CONTENT_EDITOR_GET_TO_SEND_PLAIN) != 0) {
-                       content_data["to-send-plain"] = EvoConvertToPlainText(document.body);
+                       content_data["to-send-plain"] = EvoConvert.ToPlainText(document.body);
                }
        } finally {
                try {
diff --git a/data/webkit/e-web-view.js b/data/webkit/e-web-view.js
index 7de0a891f4..b6c6cdcc67 100644
--- a/data/webkit/e-web-view.js
+++ b/data/webkit/e-web-view.js
@@ -421,12 +421,12 @@ Evo.getElementContent = function(node, format, useOuterHTML)
        var data;
 
        if (format == 1) {
-               data = EvoConvertToPlainText(node);
+               data = EvoConvert.ToPlainText(node);
        } else if (format == 2) {
                data = useOuterHTML ? node.outerHTML : node.innerHTML;
        } else if (format == 3) {
                data = {};
-               data["plain"] = EvoConvertToPlainText(node);
+               data["plain"] = EvoConvert.ToPlainText(node);
                data["html"] = useOuterHTML ? node.outerHTML : node.innerHTML;
        }
 
diff --git a/src/e-util/test-web-view-jsc.c b/src/e-util/test-web-view-jsc.c
index c4a6644773..144e5b8534 100644
--- a/src/e-util/test-web-view-jsc.c
+++ b/src/e-util/test-web-view-jsc.c
@@ -1415,6 +1415,7 @@ test_selection (TestFixture *fixture)
                "<font color=\"red\">R</font>"
                "<font color=\"green\">G</font>"
                "<font color=\"blue\">B</font>"
+               "<span id=\"rgb-end\"></span>"
                "</div>"
                "<div id=\"styled\">"
                "<span style=\"color:blue;\">bb</span>"
@@ -1444,16 +1445,23 @@ test_selection (TestFixture *fixture)
        test_selection_select_in_iframe (fixture, "frm1", "plain", "rgb");
 
        g_assert_cmpint (e_web_view_has_selection (E_WEB_VIEW (fixture->web_view)) ? 1 : 0, ==, 1);
-       test_selection_verify (fixture, "unformatted text\n", NULL);
+       test_selection_verify (fixture, "unformatted text\n\n", NULL);
        test_selection_verify (fixture, NULL, "<div id=\"plain\">unformatted text</div><br><div 
id=\"rgb\"></div>");
-       test_selection_verify (fixture, "unformatted text\n", "<div id=\"plain\">unformatted 
text</div><br><div id=\"rgb\"></div>");
+       test_selection_verify (fixture, "unformatted text\n\n", "<div id=\"plain\">unformatted 
text</div><br><div id=\"rgb\"></div>");
 
        test_selection_select_in_iframe (fixture, "frm1", "rgb", "styled");
 
+       g_assert_cmpint (e_web_view_has_selection (E_WEB_VIEW (fixture->web_view)) ? 1 : 0, ==, 1);
+       test_selection_verify (fixture, "RGB\n", NULL);
+       test_selection_verify (fixture, NULL, "<div id=\"rgb\"><font color=\"red\">R</font><font 
color=\"green\">G</font><font color=\"blue\">B</font><span id=\"rgb-end\"></span></div><div 
id=\"styled\"></div>");
+       test_selection_verify (fixture, "RGB\n", "<div id=\"rgb\"><font color=\"red\">R</font><font 
color=\"green\">G</font><font color=\"blue\">B</font><span id=\"rgb-end\"></span></div><div 
id=\"styled\"></div>");
+
+       test_selection_select_in_iframe (fixture, "frm1", "rgb", "rgb-end");
+
        g_assert_cmpint (e_web_view_has_selection (E_WEB_VIEW (fixture->web_view)) ? 1 : 0, ==, 1);
        test_selection_verify (fixture, "RGB", NULL);
-       test_selection_verify (fixture, NULL, "<div id=\"rgb\"><font color=\"red\">R</font><font 
color=\"green\">G</font><font color=\"blue\">B</font></div><div id=\"styled\"></div>");
-       test_selection_verify (fixture, "RGB", "<div id=\"rgb\"><font color=\"red\">R</font><font 
color=\"green\">G</font><font color=\"blue\">B</font></div><div id=\"styled\"></div>");
+       test_selection_verify (fixture, NULL, "<font color=\"red\">R</font><font 
color=\"green\">G</font><font color=\"blue\">B</font>");
+       test_selection_verify (fixture, "RGB", "<font color=\"red\">R</font><font 
color=\"green\">G</font><font color=\"blue\">B</font>");
 
        test_selection_select_in_iframe (fixture, "frm1", "styled", "end");
 
@@ -1683,6 +1691,7 @@ test_get_content (TestFixture *fixture)
        test_get_element_content_verify (fixture, "frm1", "frst", TRUE, NULL, expect_html);
        test_get_element_content_verify (fixture, "frm1", "frst", TRUE, expect_plain, expect_html);
 
+       expect_plain = "frm1 div\n";
        test_get_element_content_verify (fixture, "frm1", "frm1p", FALSE, expect_plain, NULL);
        test_get_element_content_verify (fixture, "frm1", "frm1p", FALSE, NULL, expect_html);
        test_get_element_content_verify (fixture, "frm1", "frm1p", FALSE, expect_plain, expect_html);
@@ -1918,6 +1927,608 @@ test_get_element_from_point (TestFixture *fixture)
        g_assert_cmpint (tested, >, 0);
 }
 
+static void
+test_convert_to_plain (TestFixture *fixture)
+{
+       #define HTML(_body) ("<html><head><style><!-- span.Apple-tab-span { white-space:pre; } 
--></style></head><body style='font-family:monospace;'>" _body "</body></html>")
+       #define TAB "<span class='Apple-tab-span' style='white-space:pre;'>\t</span>"
+       #define BREAK_STYLE " word-break:break-word; word-wrap:break-word; line-break:after-white-space;"
+       #define WRAP_STYLE(_type) " white-space:" _type "; " BREAK_STYLE
+       #define ALIGN_STYLE(_type) " text-align:" _type ";"
+       #define INDENT_STYLE(_type, _val) " margin-" _type ":" _val "ch;"
+       #define DIR_STYLE(_type) " direction:" _type ";"
+
+       struct _tests {
+               const gchar *html;
+               const gchar *plain;
+               gint normal_div_width;
+       } tests[] = {
+       /* 0 */ { HTML ("<div style='width:10ch; " BREAK_STYLE "'>123 5678 0123 5678 0123  678 
1234567890abcdefghijklmnopq 012345         356  9         " TAB TAB "0</div>"),
+                 "123 5678\n0123 5678\n0123 678\n1234567890\nabcdefghij\nklmnopq\n012345 356\n9\n0\n",
+                 -1 },
+       /* 1 */ { HTML ("<div style='width:10ch; " WRAP_STYLE ("normal") "'>123 5678 0123 5678 0123  678 
1234567890abcdefghijklmnopq 012345         356  9         " TAB TAB "0</div>"),
+                 "123 5678\n0123 5678\n0123 678\n1234567890\nabcdefghij\nklmnopq\n012345 356\n9\n0\n",
+                 -1 },
+       /* 2 */ { HTML ("<div style='width:10ch; " WRAP_STYLE ("nowrap") "'>123 5678 0123 5678 0123  678 
1234567890abcdefghijklmnopq 012345         356  9         " TAB TAB "0</div>"),
+                 "123 5678 0123 5678 0123 678 1234567890abcdefghijklmnopq 012345 356 9 0\n",
+                 -1 },
+       /* 3 */ { HTML ("<div style='width:10ch; " WRAP_STYLE ("pre") "'>123 5678 0123 5678 0123  678 
1234567890abcdefghijklmnopq 012345         356  9         " TAB TAB "0</div>"),
+                 "123 5678 0\n123 5678 0\n123  678 1\n234567890a\nbcdefghijk\nlmnopq 012\n345       \n  356  
9  \n       \t\t\n0\n",
+                 -1 },
+       /* 4 */ { HTML ("<div style='width:10ch; " WRAP_STYLE ("pre") "'>123 5678 0123 5678 0123  678 
1234567890abcdefghijklmnopq 012345         356  9          " TAB TAB "0</div>"),
+                 "123 5678 0\n123 5678 0\n123  678 1\n234567890a\nbcdefghijk\nlmnopq 012\n345       \n  356  
9  \n        \t\n\t0\n",
+                 -1 },
+       /* 5 */ { HTML ("<div style='width:10ch; " WRAP_STYLE ("pre-line") "'>123 5678 0123 5678 0123  678 
1234567890abcdefghijklmnopq 012345         356  9         " TAB TAB "0</div>"),
+                 "123 5678\n0123 5678\n0123 678\n1234567890\nabcdefghij\nklmnopq\n012345 356\n9\n0\n",
+                 -1 },
+       /* 6 */ { HTML ("<div style='width:10ch; " WRAP_STYLE ("pre-wrap") "'>123 5678 0123 5678 0123  678 
1234567890abcdefghijklmnopq 012345         356  9         " TAB TAB "0</div>"),
+                 "123 5678 \n0123 5678 \n0123  678 \n1234567890\nabcdefghij\nklmnopq \n012345    \n356  9    
\n        \n        0\n",
+                 -1 },
+       /* 7 */ { HTML ("<pre>123456789012345\n1\t90123\n123   78901\n  34567   <br>123 5</pre>"),
+                 "123456789012345\n1\t90123\n123   78901\n  34567   \n123 5\n",
+                 -1 },
+       /* 8 */ { HTML ("<pre>123456789012345\n1\t90123\n123   78901\n  34567   <br>123 5</pre>"),
+                 "123456789012345\n1\t90123\n123   78901\n  34567   \n123 5\n",
+                 10 },
+       /* 9 */ { HTML ("<h1>Header1</h1>"
+                       "<div style='width:10ch; " WRAP_STYLE ("normal") "'>123456 789 123 4567890 123456 789 
122</div>"
+                       "<div style='width:10ch; " WRAP_STYLE ("normal") "'>987654321 987 654 321 
12345678901234567890</div>"),
+                 "Header1\n\n"
+                 "123456 789\n123\n4567890\n123456 789\n122\n"
+                 "987654321\n987 654\n321\n1234567890\n1234567890\n",
+                 -1 },
+       /* 10 */{ HTML ("<h1>Header1</h1>"
+                       "<div style='width:10ch; " WRAP_STYLE ("pre-wrap") "'>123456 789 123 4567890 123456 
789 122</div>"
+                       "<div style='width:10ch; " WRAP_STYLE ("pre-wrap") "'>987654321 987 654 321 
12345678901234567890</div>"),
+                 "Header1\n\n"
+                 "123456 789\n123 \n4567890 \n123456 789\n122\n"
+                 "987654321 \n987 654 \n321 \n1234567890\n1234567890\n",
+                 -1 },
+       /* 11 */{ HTML ("<h1>H1</h1><h2>H2</h2><h3>H3</h3><h4>H4</h4><h5>H5</h5><h6>H6</h6>"),
+                 "H1\n\nH2\n\nH3\n\nH4\n\nH5\n\nH6\n\n",
+                 -1 },
+       /* 12 */{ HTML ("<address>Line 1<br>Line 2<br>Line 3 ...</address>"),
+                 "Line 1\nLine 2\nLine 3 ...\n",
+                 -1 },
+       /* 13 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") "'>1</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") "'>1 2</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") "'>1 2 3</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") "'>1 2 3 4</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") "'>1 2 3 4 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") "'>1 2 3 4 5 6</div>"),
+                 "1\n1 2\n1 2 3\n1 2 3 4\n1 2 3 4 5\n1 2 3 4 5\n6\n",
+                 -1 },
+       /* 14 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") "'>1</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") "'>1 2</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") "'>1 2 3</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") "'>1 2 3 4</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") "'>1 2 3 4 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") "'>1 2 3 4 5 6</div>"),
+                 "    1\n   1 2\n  1 2 3\n 1 2 3 4\n1 2 3 4 5\n1 2 3 4 5\n    6\n",
+                 -1 },
+       /* 15 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") "'>1</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") "'>1 2</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") "'>1 2 3</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") "'>1 2 3 4</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") "'>1 2 3 4 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") "'>1 2 3 4 5 6</div>"),
+                 "         1\n"
+                 "       1 2\n"
+                 "     1 2 3\n"
+                 "   1 2 3 4\n"
+                 " 1 2 3 4 5\n"
+                 " 1 2 3 4 5\n"
+                 "         6\n",
+                 -1 },
+       /* 16 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") "'>1 aaaaaaaaa</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") "'>1 2 aaaaaaa</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") "'>1 2 3 aaaaa</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") "'>1 2 3 4 aaa</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") "'>1 2 3 4 5 a</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") "'>1 2 3 4 5 6 
7</div>"),
+                 "1\n"
+                 "aaaaaaaaa\n"
+                 "1        2\n"
+                 "aaaaaaa\n"
+                 "1    2   3\n"
+                 "aaaaa\n"
+                 "1  2  3  4\n"
+                 "aaa\n"
+                 "1  2 3 4 5\n"
+                 "a\n"
+                 "1  2 3 4 5\n"
+                 "6 7\n",
+                 -1 },
+       /* 17 */{ HTML ("<div style='width:10ch; " BREAK_STYLE "'>123456 789 123 4567890 123456 789 
122</div>"),
+                 "123456 789\n123\n4567890\n123456 789\n122\n",
+                 -1 },
+       /* 18 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") "'>123456 789 123 4567890 
123456 789 122</div>"),
+                 "123456 789\n123\n4567890\n123456 789\n122\n",
+                 -1 },
+       /* 19 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") "'>123456 789 123 
4567890 123456 789 122</div>"),
+                 "123456 789\n"
+                 "   123\n"
+                 " 4567890\n"
+                 "123456 789\n"
+                 "   122\n",
+                 -1 },
+       /* 20 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") "'>123456 789 123 
4567890 123456 789 122</div>"),
+                 "123456 789\n"
+                 "       123\n"
+                 "   4567890\n"
+                 "123456 789\n"
+                 "       122\n",
+                 -1 },
+       /* 21 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") "'>123456 789 1 3 456 
890 1234 789 1 2 3 4 5 122</div>"),
+                 "123456 789\n"
+                 "1   3  456\n"
+                 "890   1234\n"
+                 "789  1 2 3\n"
+                 "4 5 122\n",
+                 -1 },
+       /* 22 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") DIR_STYLE ("rtl") 
"'>1</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") DIR_STYLE ("rtl") "'>1 
2</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") DIR_STYLE ("rtl") "'>1 2 
3</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") DIR_STYLE ("rtl") "'>1 2 
3 4</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") DIR_STYLE ("rtl") "'>1 2 
3 4 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") DIR_STYLE ("rtl") "'>1 2 
3 4 5 6</div>"),
+                 "1         \n"
+                 "1 2       \n"
+                 "1 2 3     \n"
+                 "1 2 3 4   \n"
+                 "1 2 3 4 5 \n"
+                 "1 2 3 4 5 \n"
+                 "6         \n",
+                 -1 },
+       /* 23 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") DIR_STYLE ("rtl") 
"'>1</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") DIR_STYLE ("rtl") "'>1 
2</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") DIR_STYLE ("rtl") "'>1 
2 3</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") DIR_STYLE ("rtl") "'>1 
2 3 4</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") DIR_STYLE ("rtl") "'>1 
2 3 4 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") DIR_STYLE ("rtl") "'>1 
2 3 4 5 6</div>"),
+                 "1    \n1 2   \n1 2 3  \n1 2 3 4 \n1 2 3 4 5\n1 2 3 4 5\n6    \n",
+                 -1 },
+       /* 24 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") DIR_STYLE ("rtl") 
"'>1</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") DIR_STYLE ("rtl") "'>1 
2</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") DIR_STYLE ("rtl") "'>1 2 
3</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") DIR_STYLE ("rtl") "'>1 2 
3 4</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") DIR_STYLE ("rtl") "'>1 2 
3 4 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") DIR_STYLE ("rtl") "'>1 2 
3 4 5 6</div>"),
+                 "1\n1 2\n1 2 3\n1 2 3 4\n1 2 3 4 5\n1 2 3 4 5\n6\n",
+                 -1 },
+       /* 25 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") DIR_STYLE ("rtl") "'>1 
aaaaaaaaa</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") DIR_STYLE ("rtl") "'>1 
2 aaaaaaa</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") DIR_STYLE ("rtl") "'>1 
2 3 aaaaa</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") DIR_STYLE ("rtl") "'>1 
2 3 4 aaa</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") DIR_STYLE ("rtl") "'>1 
2 3 4 5 a</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") DIR_STYLE ("rtl") "'>1 
2 3 4 5 6 7</div>"),
+                 "1\n"
+                 "aaaaaaaaa\n"
+                 "1        2\n"
+                 "aaaaaaa\n"
+                 "1    2   3\n"
+                 "aaaaa\n"
+                 "1  2  3  4\n"
+                 "aaa\n"
+                 "1  2 3 4 5\n"
+                 "a\n"
+                 "1  2 3 4 5\n"
+                 "6 7\n",
+                 -1 },
+       /* 26 */{ HTML ("<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("rtl") "'>123456 789 123 4567890 
123456 789 122</div>"),
+                 "123456 789\n"
+                 "123\n"
+                 "4567890\n"
+                 "123456 789\n"
+                 "122\n",
+                 -1 },
+       /* 27 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") DIR_STYLE ("rtl") 
"'>123456 789 123 4567890 123456 789 122</div>"),
+                 "123456 789\n"
+                 "123       \n"
+                 "4567890   \n"
+                 "123456 789\n"
+                 "122       \n",
+                 -1 },
+       /* 28 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") DIR_STYLE ("rtl") 
"'>123456 789 123 4567890 123456 789 122</div>"),
+                 "123456 789\n"
+                 "123   \n"
+                 "4567890 \n"
+                 "123456 789\n"
+                 "122   \n",
+                 -1 },
+       /* 29 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("right") DIR_STYLE ("rtl") 
"'>123456 789 123 4567890 123456 789 122</div>"),
+                 "123456 789\n123\n4567890\n123456 789\n122\n",
+                 -1 },
+       /* 30 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") DIR_STYLE ("rtl") 
"'>123456 789 1 3 456 890 1234 789 1 2 3 4 5 122</div>"),
+                 "123456 789\n"
+                 "1   3  456\n"
+                 "890   1234\n"
+                 "789  1 2 3\n"
+                 "4 5 122\n",
+                 -1 },
+       /* 31 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") INDENT_STYLE ("left", 
"3") "'>123 567 901 345 789 123 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") INDENT_STYLE ("left", 
"6") "'>987 543 109 765 321 098 6</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("left") INDENT_STYLE ("left", 
"3") "'>111 222 333 444 555 666 7</div>"),
+                 "   123 567\n"
+                 "   901 345\n"
+                 "   789 123 5\n"
+                 "      987 543\n"
+                 "      109 765\n"
+                 "      321 098 6\n"
+                 "   111 222\n"
+                 "   333 444\n"
+                 "   555 666 7\n",
+                 -1 },
+       /* 32 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") INDENT_STYLE ("left", 
"3") "'>123 567 901 345 789 123 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") INDENT_STYLE ("left", 
"6") "'>987 543 109 765 321 098 6</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("center") INDENT_STYLE ("left", 
"3") "'>111 222 333 444 555 666 7</div>"),
+                 "    123 567\n"
+                 "    901 345\n"
+                 "   789 123 5\n"
+                 "       987 543\n"
+                 "       109 765\n"
+                 "      321 098 6\n"
+                 "    111 222\n"
+                 "    333 444\n"
+                 "   555 666 7\n",
+                 -1 },
+       /* 33 */{ HTML ("<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("rtl") INDENT_STYLE ("right", "3") 
"'>123 567 901 345 789 123 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("rtl") INDENT_STYLE ("right", "6") 
"'>987 543 109 765 321 098 6</div>"
+                       "<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("rtl") INDENT_STYLE ("right", "3") 
"'>111 222 333 444 555 666 7</div>"),
+                 "123 567   \n"
+                 "901 345   \n"
+                 "789 123 5   \n"
+                 "987 543      \n"
+                 "109 765      \n"
+                 "321 098 6      \n"
+                 "111 222   \n"
+                 "333 444   \n"
+                 "555 666 7   \n",
+                 -1 },
+       /* 34 */{ HTML ("<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("ltr") ALIGN_STYLE ("right") 
INDENT_STYLE ("left", "3") "'>123 567 901 345 789 123 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("ltr") ALIGN_STYLE ("right") 
INDENT_STYLE ("left", "6") "'>987 543 109 765 321 098 6</div>"
+                       "<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("ltr") ALIGN_STYLE ("right") 
INDENT_STYLE ("left", "3") "'>111 222 333 444 555 666 7</div>"),
+                 "   123 567\n"
+                 "   901 345\n"
+                 " 789 123 5\n"
+                 "   987 543\n"
+                 "   109 765\n"
+                 " 321 098 6\n"
+                 "   111 222\n"
+                 "   333 444\n"
+                 " 555 666 7\n",
+                 -1 },
+       /* 35 */{ HTML ("<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("rtl") ALIGN_STYLE ("left") 
INDENT_STYLE ("right", "3") "'>123 567 901 345 789 123 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("rtl") ALIGN_STYLE ("left") 
INDENT_STYLE ("right", "6") "'>987 543 109 765 321 098 6</div>"
+                       "<div style='width:10ch; " BREAK_STYLE DIR_STYLE ("rtl") ALIGN_STYLE ("left") 
INDENT_STYLE ("right", "3") "'>111 222 333 444 555 666 7</div>"),
+                 "123 567   \n"
+                 "901 345   \n"
+                 "789 123 5 \n"
+                 "987 543   \n"
+                 "109 765   \n"
+                 "321 098 6 \n"
+                 "111 222   \n"
+                 "333 444   \n"
+                 "555 666 7 \n",
+                 -1 },
+       /* 36 */{ HTML ("<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") INDENT_STYLE ("left", 
"3") "'>123 567 901 345 789 123 5</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") INDENT_STYLE ("left", 
"6") "'>987 543 109 765 321 098 6</div>"
+                       "<div style='width:10ch; " BREAK_STYLE ALIGN_STYLE ("justify") INDENT_STYLE ("left", 
"3") "'>111 222 333 444 555 666 7</div>"),
+                 "   123    567\n"
+                 "   901    345\n"
+                 "   789 123 5\n"
+                 "      987    543\n"
+                 "      109    765\n"
+                 "      321 098 6\n"
+                 "   111    222\n"
+                 "   333    444\n"
+                 "   555 666 7\n",
+                 -1 },
+       /* 37 */{ HTML ("<ul style='width: 9ch;'>"
+                       "<li>1 11 111 1111 111 11 1</li>"
+                       "<li>2 22 222 2222 222 22 2</li>"
+                       "<li>3 33 333 3333 33333 333 33 3</li>"
+                       "</ul>"),
+                 " * 1 11 111\n"
+                 "   1111 111\n"
+                 "   11 1\n"
+                 " * 2 22 222\n"
+                 "   2222 222\n"
+                 "   22 2\n"
+                 " * 3 33 333\n"
+                 "   3333\n"
+                 "   33333 333\n"
+                 "   33 3\n",
+                 -1 },
+       /* 38 */{ HTML ("<ol style='width: 9ch;'>"
+                       "<li>1 11 111 1111 111 11 1</li>"
+                       "<li>2 22 222 2222 222 22 2</li>"
+                       "<li>3 33 333 3333 33333 333 33 3</li>"
+                       "</ol>"),
+                 "   1. 1 11 111\n"
+                 "      1111 111\n"
+                 "      11 1\n"
+                 "   2. 2 22 222\n"
+                 "      2222 222\n"
+                 "      22 2\n"
+                 "   3. 3 33 333\n"
+                 "      3333\n"
+                 "      33333 333\n"
+                 "      33 3\n",
+                 -1 },
+       /* 39 */{ HTML ("<ol type='A' style='width: 9ch;'>"
+                       "<li>1 11 111 1111 111 11 1</li>"
+                       "<li>2 22 222 2222 222 22 2</li>"
+                       "<li>3 33 333 3333 33333 333 33 3</li>"
+                       "</ol>"),
+                 "   A. 1 11 111\n"
+                 "      1111 111\n"
+                 "      11 1\n"
+                 "   B. 2 22 222\n"
+                 "      2222 222\n"
+                 "      22 2\n"
+                 "   C. 3 33 333\n"
+                 "      3333\n"
+                 "      33333 333\n"
+                 "      33 3\n",
+                 -1 },
+       /* 40 */{ HTML ("<ol type='a' style='width: 9ch;'>"
+                       "<li>1 11 111 1111 111 11 1</li>"
+                       "<li>2 22 222 2222 222 22 2</li>"
+                       "<li>3 33 333 3333 33333 333 33 3</li>"
+                       "</ol>"),
+                 "   a. 1 11 111\n"
+                 "      1111 111\n"
+                 "      11 1\n"
+                 "   b. 2 22 222\n"
+                 "      2222 222\n"
+                 "      22 2\n"
+                 "   c. 3 33 333\n"
+                 "      3333\n"
+                 "      33333 333\n"
+                 "      33 3\n",
+                 -1 },
+       /* 41 */{ HTML ("<ol type='I' style='width: 9ch;'>"
+                       "<li>1 11 111 1111 111 11 1</li>"
+                       "<li>2 22 222 2222 222 22 2</li>"
+                       "<li>3 33 333 3333 33333 333 33 3</li>"
+                       "</ol>"),
+                 "   I. 1 11 111\n"
+                 "      1111 111\n"
+                 "      11 1\n"
+                 "  II. 2 22 222\n"
+                 "      2222 222\n"
+                 "      22 2\n"
+                 " III. 3 33 333\n"
+                 "      3333\n"
+                 "      33333 333\n"
+                 "      33 3\n",
+                 -1 },
+       /* 42 */{ HTML ("<ol type='i' style='width: 9ch;'>"
+                       "<li>1 11 111 1111 111 11 1</li>"
+                       "<li>2 22 222 2222 222 22 2</li>"
+                       "<li>3 33 333 3333 33333 333 33 3</li>"
+                       "</ol>"),
+                 "   i. 1 11 111\n"
+                 "      1111 111\n"
+                 "      11 1\n"
+                 "  ii. 2 22 222\n"
+                 "      2222 222\n"
+                 "      22 2\n"
+                 " iii. 3 33 333\n"
+                 "      3333\n"
+                 "      33333 333\n"
+                 "      33 3\n",
+                 -1 },
+       /* 43 */{ HTML ("<ol type='i' style='width: 9ch;'>"
+                       "<li>1</li>"
+                       "<li>2</li>"
+                       "<li>3</li>"
+                       "<li>4</li>"
+                       "<li>5</li>"
+                       "<li>6</li>"
+                       "<li>7</li>"
+                       "<li>8</li>"
+                       "<li>9</li>"
+                       "<li>10</li>"
+                       "<li>11</li>"
+                       "<li>12</li>"
+                       "<li>13</li>"
+                       "<li>14</li>"
+                       "<li>15</li>"
+                       "<li>16</li>"
+                       "<li>17</li>"
+                       "<li>18</li>"
+                       "<li>19</li>"
+                       "<li>20</li>"
+                       "</ol>"),
+                 "    i. 1\n"
+                 "   ii. 2\n"
+                 "  iii. 3\n"
+                 "   iv. 4\n"
+                 "    v. 5\n"
+                 "   vi. 6\n"
+                 "  vii. 7\n"
+                 " viii. 8\n"
+                 "   ix. 9\n"
+                 "    x. 10\n"
+                 "   xi. 11\n"
+                 "  xii. 12\n"
+                 " xiii. 13\n"
+                 "  xiv. 14\n"
+                 "   xv. 15\n"
+                 "  xvi. 16\n"
+                 " xvii. 17\n"
+                 "xviii. 18\n"
+                 "  xix. 19\n"
+                 "   xx. 20\n",
+                 -1 },
+       /* 44 */{ HTML ("<ol style='width: 9ch; " DIR_STYLE ("rtl") "'>"
+                       "<li>1 11 111 1111 111 11 1</li>"
+                       "<li>2 22 222 2222 222 22 2</li>"
+                       "<li>3 33 333 3333 33333 333 33 3</li>"
+                       "<li>4</li>"
+                       "</ol>"),
+                 "1 11 111 .1   \n"
+                 "1111 111      \n"
+                 "11 1      \n"
+                 "2 22 222 .2   \n"
+                 "2222 222      \n"
+                 "22 2      \n"
+                 "3 33 333 .3   \n"
+                 "3333      \n"
+                 "33333 333      \n"
+                 "33 3      \n"
+                 "4 .4   \n",
+                 -1 },
+       /* 45 */{ HTML ("<ol type='I' style='width: 9ch; " DIR_STYLE ("rtl") "'>"
+                       "<li>1</li>"
+                       "<li>2</li>"
+                       "<li>3</li>"
+                       "<li>4</li>"
+                       "<li>5</li>"
+                       "<li>6</li>"
+                       "<li>7</li>"
+                       "<li>8</li>"
+                       "<li>9</li>"
+                       "<li>10</li>"
+                       "<li>11</li>"
+                       "<li>12</li>"
+                       "<li>13</li>"
+                       "<li>14</li>"
+                       "<li>15</li>"
+                       "<li>16</li>"
+                       "<li>17</li>"
+                       "<li>18</li>"
+                       "<li>19</li>"
+                       "<li>20</li>"
+                       "</ol>"),
+                 "1 .I    \n"
+                 "2 .II   \n"
+                 "3 .III  \n"
+                 "4 .IV   \n"
+                 "5 .V    \n"
+                 "6 .VI   \n"
+                 "7 .VII  \n"
+                 "8 .VIII \n"
+                 "9 .IX   \n"
+                 "10 .X    \n"
+                 "11 .XI   \n"
+                 "12 .XII  \n"
+                 "13 .XIII \n"
+                 "14 .XIV  \n"
+                 "15 .XV   \n"
+                 "16 .XVI  \n"
+                 "17 .XVII \n"
+                 "18 .XVIII\n"
+                 "19 .XIX  \n"
+                 "20 .XX   \n",
+                 -1 },
+       /* 46 */{ HTML ("<ul style='width: 15ch; padding-inline-start: 3ch;'>"
+                       "<li>AA 1 2 3 4 5 6 7 8 9 11 22 33</li>"
+                       "<ul style='width: 12ch; padding-inline-start: 3ch;'>"
+                       "<li>BA 1 2 3 4 5 6 7 8 9</li>"
+                       "<li>BB 1 2 3 4 5 6 7 8 9</li>"
+                       "<ul style='width: 9ch; padding-inline-start: 3ch;'>"
+                       "<li>CA 1 2 3 4 5 6</li>"
+                       "<li>CB 1 2 3 4 5 6</li>"
+                       "</ul>"
+                       "<li>BC 1 2 3 4 5 6</li>"
+                       "</ul>"
+                       "<li>AB 1 2 3 4 5 6 7</li>"
+                       "</ul>"),
+                 " * AA 1 2 3 4 5 6\n"
+                 "   7 8 9 11 22 33\n"
+                 "    # BA 1 2 3 4 5\n"
+                 "      6 7 8 9\n"
+                 "    # BB 1 2 3 4 5\n"
+                 "      6 7 8 9\n"
+                 "       * CA 1 2 3\n"
+                 "         4 5 6\n"
+                 "       * CB 1 2 3\n"
+                 "         4 5 6\n"
+                 "    # BC 1 2 3 4 5\n"
+                 "      6\n"
+                 " * AB 1 2 3 4 5 6\n"
+                 "   7\n",
+                 -1 },
+       /* 47 */{ HTML ("<ol>"
+                         "<li>1</li>"
+                         "<ul>"
+                           "<li>1.#</li>"
+                           "<ol type='i'>"
+                             "<li>1.#.i</li>"
+                             "<ol type='a'>"
+                               "<li>1.#.i.a</li>"
+                               "<li>1.#.i.b</li>"
+                             "</ol>"
+                             "<li>1.#.ii</li>"
+                             "<ol type='A'>"
+                               "<li>1.#.ii.A</li>"
+                               "<ul>"
+                                 "<li>1.#.ii.A.*</li>"
+                                 "<ul>"
+                                   "<li>1.#.ii.A.*.#</li>"
+                                      "<ol type='I'>"
+                                         "<li>1.#.ii.A.*.#.I</li>"
+                                         "<li>1.#.ii.A.*.#.II</li>"
+                                         "<li>1.#.ii.A.*.#.III</li>"
+                                      "</ol>"
+                                   "<li>1.#.ii.A.*.#</li>"
+                                 "</ul>"
+                                 "<li>1.#.ii.A.*</li>"
+                               "</ul>"
+                               "<li>1.#.ii.B</li>"
+                             "</ol>"
+                             "<li>1.#.iii</li>"
+                           "</ol>"
+                           "<li>1.#</li>"
+                         "</ul>"
+                         "<li>2</li>"
+                       "</ol>"),
+                 "   1. 1\n"
+                 "       # 1.#\n"
+                 "         i. 1.#.i\n"
+                 "               a. 1.#.i.a\n"
+                 "               b. 1.#.i.b\n"
+                 "        ii. 1.#.ii\n"
+                 "               A. 1.#.ii.A\n"
+                 "                   * 1.#.ii.A.*\n"
+                 "                      # 1.#.ii.A.*.#\n"
+                 "                     I. 1.#.ii.A.*.#.I\n"
+                 "                    II. 1.#.ii.A.*.#.II\n"
+                 "                   III. 1.#.ii.A.*.#.III\n"
+                 "                      # 1.#.ii.A.*.#\n"
+                 "                   * 1.#.ii.A.*\n"
+                 "               B. 1.#.ii.B\n"
+                 "       iii. 1.#.iii\n"
+                 "       # 1.#\n"
+                 "   2. 2\n",
+                 -1 }
+       };
+
+       #undef HTML
+       #undef TAB
+       #undef BREAK_STYLE
+       #undef WRAP_STYLE
+       #undef ALIGN_STYLE
+       #undef INDENT_STYLE
+       #undef DIR_STYLE
+
+       gchar *script;
+       gint ii;
+
+       for (ii = 0; ii < G_N_ELEMENTS (tests); ii++) {
+               test_utils_load_string (fixture, tests[ii].html);
+
+               script = e_web_view_jsc_printf_script ("EvoConvert.ToPlainText(document.body, %d);", 
tests[ii].normal_div_width);
+
+               test_utils_jsc_call_string_and_verify (fixture, script, tests[ii].plain);
+
+               g_free (script);
+       }
+}
+
 gint
 main (gint argc,
       gchar *argv[])
@@ -1948,6 +2559,7 @@ main (gint argc,
        test_utils_add_test ("/EWebView/Selection", test_selection);
        test_utils_add_test ("/EWebView/GetContent", test_get_content);
        test_utils_add_test ("/EWebView/GetElementFromPoint", test_get_element_from_point);
+       test_utils_add_test ("/EWebView/ConvertToPlain", test_convert_to_plain);
 
        res = g_test_run ();
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]