Add plaintext quote marker to blockquote lines in one pass
This commit is contained in:
parent
03a18fbef0
commit
a9efe8fd3a
2 changed files with 19 additions and 125 deletions
|
|
@ -23,8 +23,6 @@ class ComposerPageStateTest : ClientWebViewTestCase<ComposerWebView> {
|
|||
add_test("get_text_with_nested_quote", get_text_with_nested_quote);
|
||||
|
||||
add_test("contains_keywords", contains_keywords);
|
||||
add_test("quote_lines", quote_lines);
|
||||
add_test("resolve_nesting", resolve_nesting);
|
||||
add_test("replace_non_breaking_space", replace_non_breaking_space);
|
||||
|
||||
try {
|
||||
|
|
@ -271,59 +269,6 @@ unknown://example6.com
|
|||
}
|
||||
}
|
||||
|
||||
public void resolve_nesting() throws Error {
|
||||
load_body_fixture();
|
||||
unichar q_marker = Geary.RFC822.Utils.QUOTE_MARKER;
|
||||
unichar q_start = '';
|
||||
unichar q_end = '';
|
||||
string js_no_quote = "foo";
|
||||
string js_spaced_quote = @"foo $(q_start)0$(q_end) bar";
|
||||
string js_leading_quote = @"$(q_start)0$(q_end) bar";
|
||||
string js_hanging_quote = @"foo $(q_start)0$(q_end)";
|
||||
string js_cosy_quote1 = @"foo$(q_start)0$(q_end)bar";
|
||||
string js_cosy_quote2 = @"foo$(q_start)0$(q_end)$(q_start)1$(q_end)bar";
|
||||
string js_values = "['quote1','quote2']";
|
||||
try {
|
||||
assert(WebKitUtil.to_string(run_javascript(@"ComposerPageState.resolveNesting('$(js_no_quote)', $(js_values));")) ==
|
||||
@"foo");
|
||||
assert(WebKitUtil.to_string(run_javascript(@"ComposerPageState.resolveNesting('$(js_spaced_quote)', $(js_values));")) ==
|
||||
@"foo $(q_marker)quote1 bar");
|
||||
assert(WebKitUtil.to_string(run_javascript(@"ComposerPageState.resolveNesting('$(js_leading_quote)', $(js_values));")) ==
|
||||
@"$(q_marker)quote1 bar");
|
||||
assert(WebKitUtil.to_string(run_javascript(@"ComposerPageState.resolveNesting('$(js_hanging_quote)', $(js_values));")) ==
|
||||
@"foo $(q_marker)quote1");
|
||||
assert(WebKitUtil.to_string(run_javascript(@"ComposerPageState.resolveNesting('$(js_cosy_quote1)', $(js_values));")) ==
|
||||
@"foo$(q_marker)quote1bar");
|
||||
assert(WebKitUtil.to_string(run_javascript(@"ComposerPageState.resolveNesting('$(js_cosy_quote2)', $(js_values));")) ==
|
||||
@"foo$(q_marker)quote1$(q_marker)quote2bar");
|
||||
} catch (Geary.JS.Error err) {
|
||||
print("Geary.JS.Error: %s\n", err.message);
|
||||
assert_not_reached();
|
||||
} catch (Error err) {
|
||||
print("WKError: %s\n", err.message);
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
public void quote_lines() throws Error {
|
||||
load_body_fixture();
|
||||
unichar q_marker = Geary.RFC822.Utils.QUOTE_MARKER;
|
||||
try {
|
||||
assert(WebKitUtil.to_string(run_javascript("ComposerPageState.quoteLines('');")) ==
|
||||
@"$(q_marker)");
|
||||
assert(WebKitUtil.to_string(run_javascript("ComposerPageState.quoteLines('line1');")) ==
|
||||
@"$(q_marker)line1");
|
||||
assert(WebKitUtil.to_string(run_javascript("ComposerPageState.quoteLines('line1\\nline2');")) ==
|
||||
@"$(q_marker)line1\n$(q_marker)line2");
|
||||
} catch (Geary.JS.Error err) {
|
||||
print("Geary.JS.Error: %s\n", err.message);
|
||||
assert_not_reached();
|
||||
} catch (Error err) {
|
||||
print("WKError: %s\n", err.message);
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
public void replace_non_breaking_space() throws Error {
|
||||
load_body_fixture();
|
||||
string single_nbsp = "a b";
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ let ComposerPageState = function() {
|
|||
this.init.apply(this, arguments);
|
||||
};
|
||||
ComposerPageState.KEYWORD_SPLIT_REGEX = /[\s]+/g;
|
||||
ComposerPageState.QUOTE_START = "\x91"; // private use one
|
||||
ComposerPageState.QUOTE_END = "\x92"; // private use two
|
||||
ComposerPageState.QUOTE_MARKER = "\x7f"; // delete
|
||||
ComposerPageState.PROTOCOL_REGEX = /^(aim|apt|bitcoin|cvs|ed2k|ftp|file|finger|git|gtalk|http|https|irc|ircs|irc6|lastfm|ldap|ldaps|magnet|news|nntp|rsync|sftp|skype|smb|sms|svn|telnet|tftp|ssh|webcal|xmpp):/i;
|
||||
// Taken from Geary.HTML.URL_REGEX, without the inline modifier (?x)
|
||||
|
|
@ -330,7 +328,8 @@ ComposerPageState.prototype = {
|
|||
return parent.innerHTML;
|
||||
},
|
||||
getText: function() {
|
||||
return ComposerPageState.htmlToQuotedText(document.body);
|
||||
let text = ComposerPageState.htmlToText(document.body);
|
||||
return ComposerPageState.replaceNonBreakingSpace(text);
|
||||
},
|
||||
setRichText: function(enabled) {
|
||||
if (enabled) {
|
||||
|
|
@ -440,25 +439,6 @@ ComposerPageState.cleanPart = function(part, removeIfEmpty) {
|
|||
return part;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a HTML DOM tree to plain text with delineated quotes.
|
||||
*
|
||||
* Lines are delinated using LF. Quoted lines are prefixed with
|
||||
* `ComposerPageState.QUOTE_MARKER`, where the number of markers
|
||||
* indicates the depth of nesting of the quote.
|
||||
*/
|
||||
ComposerPageState.htmlToQuotedText = function(root) {
|
||||
let bqTexts = [];
|
||||
|
||||
text = ComposerPageState.htmlToTextAndQuotes(root, bqTexts);
|
||||
|
||||
// Reassemble plain text out of parts, and replace non-breaking
|
||||
// space with regular space.
|
||||
text = ComposerPageState.resolveNesting(text, bqTexts);
|
||||
|
||||
return ComposerPageState.replaceNonBreakingSpace(text);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets plain text that adequately represents the information in the HTML
|
||||
*
|
||||
|
|
@ -466,10 +446,11 @@ ComposerPageState.htmlToQuotedText = function(root) {
|
|||
* underscores around underlined text. Link URLs are inserted after the link
|
||||
* text.
|
||||
*
|
||||
* Blockquotes are extracted and replaced with tokens deliminated with the
|
||||
* characters QUOTE_START and QUOTE_END (from a unicode private use block).
|
||||
* Each line of a blockquote is prefixed with
|
||||
* `ComposerPageState.QUOTE_MARKER`, where the number of markers indicates
|
||||
* the depth of nesting of the quote.
|
||||
*/
|
||||
ComposerPageState.htmlToTextAndQuotes = function(root, bqTexts) {
|
||||
ComposerPageState.htmlToText = function(root) {
|
||||
let parentStyle = window.getComputedStyle(root);
|
||||
let text = "";
|
||||
|
||||
|
|
@ -509,37 +490,38 @@ ComposerPageState.htmlToTextAndQuotes = function(root, bqTexts) {
|
|||
if (node.textContent == node.href) {
|
||||
text += "<" + node.href + ">";
|
||||
} else {
|
||||
text += ComposerPageState.htmlToTextAndQuotes(node, bqTexts);
|
||||
text += ComposerPageState.htmlToText(node);
|
||||
text += " <" + node.href + ">";
|
||||
}
|
||||
break;
|
||||
case "b":
|
||||
case "strong":
|
||||
text += "*" + ComposerPageState.htmlToTextAndQuotes(node, bqTexts) + "*";
|
||||
text += "*" + ComposerPageState.htmlToText(node) + "*";
|
||||
break;
|
||||
case "blockquote":
|
||||
let bqText = ComposerPageState.htmlToTextAndQuotes(node, bqTexts);
|
||||
text += (
|
||||
ComposerPageState.QUOTE_START
|
||||
+ bqTexts.length.toString()
|
||||
+ ComposerPageState.QUOTE_END
|
||||
);
|
||||
bqTexts.push(bqText);
|
||||
let bqText = ComposerPageState.htmlToText(node);
|
||||
// If there is a newline at the end of the quote, remove it
|
||||
// After this switch we ensure that there is a newline after the quote
|
||||
bqText = bqText.replace(/\n$/, "");
|
||||
let lines = bqText.split("\n");
|
||||
for (let i = 0; i < lines.length; i++)
|
||||
lines[i] = ComposerPageState.QUOTE_MARKER + lines[i];
|
||||
text += lines.join("\n");
|
||||
break;
|
||||
case "br":
|
||||
text += "\n";
|
||||
break;
|
||||
case "i":
|
||||
case "em":
|
||||
text += "/" + ComposerPageState.htmlToTextAndQuotes(node, bqTexts) + "/";
|
||||
text += "/" + ComposerPageState.htmlToText(node) + "/";
|
||||
break;
|
||||
case "u":
|
||||
text += "_" + ComposerPageState.htmlToTextAndQuotes(node, bqTexts) + "_";
|
||||
text += "_" + ComposerPageState.htmlToText(node) + "_";
|
||||
break;
|
||||
case "#comment":
|
||||
break;
|
||||
default:
|
||||
text += ComposerPageState.htmlToTextAndQuotes(node, bqTexts);
|
||||
text += ComposerPageState.htmlToText(node);
|
||||
break;
|
||||
}
|
||||
if (isBlock) {
|
||||
|
|
@ -607,39 +589,6 @@ ComposerPageState.linkify = function(node) {
|
|||
}
|
||||
};
|
||||
|
||||
ComposerPageState.resolveNesting = function(text, values) {
|
||||
let tokenregex = new RegExp(
|
||||
ComposerPageState.QUOTE_START
|
||||
+ "([0-9]+)"
|
||||
+ ComposerPageState.QUOTE_END, "g"
|
||||
);
|
||||
return text.replace(tokenregex, function(match, p1, offset, str) {
|
||||
let key = new Number(p1);
|
||||
|
||||
let value = "";
|
||||
if (key >= 0 && key < values.length) {
|
||||
let nested = ComposerPageState.resolveNesting(values[key], values);
|
||||
// If there is a newline at the end of the quote, remove it
|
||||
// htmltoTextandQuotes already ensured that there is a newline after the quote
|
||||
nested = nested.replace(/\n$/, "");
|
||||
value = ComposerPageState.quoteLines(nested);
|
||||
} else {
|
||||
console.error("Regex error in denesting blockquotes: Invalid key");
|
||||
}
|
||||
return value;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Prefixes each NL-delineated line with `ComposerPageState.QUOTE_MARKER`.
|
||||
*/
|
||||
ComposerPageState.quoteLines = function(text) {
|
||||
let lines = text.split("\n");
|
||||
for (let i = 0; i < lines.length; i++)
|
||||
lines[i] = ComposerPageState.QUOTE_MARKER + lines[i];
|
||||
return lines.join("\n");
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts all non-breaking space chars to plain spaces.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue