diff --git a/src/com/fsck/k9/helper/HtmlConverter.java b/src/com/fsck/k9/helper/HtmlConverter.java index e0bf6b720..7bc565e5e 100644 --- a/src/com/fsck/k9/helper/HtmlConverter.java +++ b/src/com/fsck/k9/helper/HtmlConverter.java @@ -190,6 +190,11 @@ public class HtmlConverter { return buff.toString(); } + private static final String HTML_BLOCKQUOTE_START = "
"; + private static final String HTML_BLOCKQUOTE_END = "
"; + private static final String HTML_NEWLINE = "
"; + /** * Convert a text string into an HTML document. * @@ -217,14 +222,19 @@ public class HtmlConverter { } StringReader reader = new StringReader(text); StringBuilder buff = new StringBuilder(text.length() + TEXT_TO_HTML_EXTRA_BUFFER_LENGTH); - int c; + boolean isStartOfLine = false; // Are we currently at the start of a line? + int quoteDepth = 0; // Number of DIVs deep we are. + int quotesThisLine = 0; // How deep we should be quoting for this line. try { + int c; while ((c = reader.read()) != -1) { switch (c) { case '\n': // pine treats
as two newlines, but
as one newline. Use
so our messages aren't // doublespaced. - buff.append("
"); + buff.append(HTML_NEWLINE); + isStartOfLine = true; + quotesThisLine = 0; break; case '&': buff.append("&"); @@ -233,11 +243,39 @@ public class HtmlConverter { buff.append("<"); break; case '>': - buff.append(">"); + if(isStartOfLine) { + quotesThisLine++; + } else { + buff.append(">"); + } break; case '\r': break; + case ' ': + if(isStartOfLine) { + // If we're still in the start of the line and we have spaces, don't output them, since they + // may be collapsed by our div-converting magic. + break; + } default: + if(isStartOfLine) { + // Not a quote character and not a space. Content is starting now. + isStartOfLine = false; + if(K9.DEBUG) { + Log.d(K9.LOG_TAG, "currentQuoteDepth: " + quoteDepth + " quotesThisLine: " + quotesThisLine); + } + // Add/remove blockquotes by comparing this line's quotes to the previous line's quotes. + if(quotesThisLine > quoteDepth) { + for(int i = quoteDepth; i < quotesThisLine; i++) { + buff.append(HTML_BLOCKQUOTE_START); + } + } else if(quotesThisLine < quoteDepth) { + for(int i = quoteDepth; i > quotesThisLine; i--) { + buff.append(HTML_BLOCKQUOTE_END); + } + } + quoteDepth = quotesThisLine; + } buff.append((char)c); }//switch } @@ -245,8 +283,21 @@ public class HtmlConverter { //Should never happen Log.e(K9.LOG_TAG, "Could not read string to convert text to HTML:", e); } + // Close off any quotes we may have opened. + if (quoteDepth > 0) { + for (int i = quoteDepth; i > 0; i--) { + buff.append(HTML_BLOCKQUOTE_END); + } + } text = buff.toString(); + // Make newlines at the end of blockquotes nicer by putting newlines beyond the first one outside of the + // blockquote. + text = text.replaceAll( + "\\Q" + HTML_NEWLINE + "\\E((\\Q" + HTML_NEWLINE + "\\E)+?)\\Q" + HTML_BLOCKQUOTE_END + "\\E", + HTML_BLOCKQUOTE_END + "$1" + ); + // Replace lines of -,= or _ with horizontal rules text = text.replaceAll("\\s*([-=_]{30,}+)\\s*", "
"); diff --git a/tests/src/com/fsck/k9/helper/HtmlConverterTest.java b/tests/src/com/fsck/k9/helper/HtmlConverterTest.java new file mode 100644 index 000000000..a38de64f2 --- /dev/null +++ b/tests/src/com/fsck/k9/helper/HtmlConverterTest.java @@ -0,0 +1,66 @@ +package com.fsck.k9.helper; + +import junit.framework.Assert; +import org.junit.Test; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; + +public class HtmlConverterTest { + // Useful if you want to write stuff to a file for debugging in a browser. + private static final boolean WRITE_TO_FILE = false; + private static final String OUTPUT_FILE = "C:/temp/parse.html"; + + @Test + public void testTextQuoteToHtmlBlockquote() { + String message = "Panama!\n" + + "\n" + + "Bob Barker wrote:\n" + + "> a canal\n" + + ">\n" + + "> Dorothy Jo Gideon espoused:\n" + + "> >A man, a plan...\n" + + "> Too easy!\n" + + "\n" + + "Nice job :)\n" + + ">> Guess!"; + String result = HtmlConverter.textToHtml(message, false); + writeToFile(result); + Assert.assertEquals("
Panama!

Bob Barker <bob@aol.com> wrote:
a canal

Dorothy Jo Gideon <dorothy@aol.com> espoused:
A man, a plan...
Too easy!

Nice job :)
Guess!
", result); + } + + @Test + public void testTextQuoteToHtmlBlockquoteIndented() { + String message = "*facepalm*\n" + + "\n" + + "Bob Barker wrote:\n" + + "> A wise man once said...\n" + + ">\n" + + "> LOL F1RST!!!!!\n" + + ">\n" + + "> :)"; + String result = HtmlConverter.textToHtml(message, false); + writeToFile(result); + Assert.assertEquals("
*facepalm*

Bob Barker <bob@aol.com> wrote:
A wise man once said...

LOL F1RST!!!!!

:)
", result); + } + + private void writeToFile(final String content) { + if(!WRITE_TO_FILE) { + return; + } + try { + System.err.println(content); + + File f = new File(OUTPUT_FILE); + f.delete(); + + FileWriter fstream = new FileWriter(OUTPUT_FILE); + BufferedWriter out = new BufferedWriter(fstream); + out.write(content); + out.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +}