Simplified/improved plain text

pull/178/head
M66B 5 years ago
parent 2d9fe076ba
commit c9dd9a664f

@ -4139,7 +4139,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
from = ((InternetAddress) message.from[0]).getAddress(); from = ((InternetAddress) message.from[0]).getAddress();
String html = Helper.readText(file); String html = Helper.readText(file);
String text = HtmlHelper.getText(html); String text = HtmlHelper.getText(context, html);
return new String[]{from, message.subject, text}; return new String[]{from, message.subject, text};
} }

@ -947,7 +947,7 @@ public class FragmentCompose extends FragmentBase {
Document document = JsoupEx.parse(body); Document document = JsoupEx.parse(body);
if (plain) { if (plain) {
String text = HtmlHelper.getText(ref.outerHtml()); String text = HtmlHelper.getText(context, ref.outerHtml());
String[] line = text.split("\\r?\\n"); String[] line = text.split("\\r?\\n");
for (int i = 0; i < line.length; i++) for (int i = 0; i < line.length; i++)
line[i] = Html.escapeHtml(line[i]); line[i] = Html.escapeHtml(line[i]);

@ -1487,106 +1487,61 @@ public class HtmlHelper {
return preview; return preview;
} }
static String getText(String html) { static String getText(Context context, String html) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
html = html.replace("<br> ", "<br>");
Document d = JsoupEx.parse(html); Document d = JsoupEx.parse(html);
truncate(d, true); truncate(d, true);
NodeTraversor.traverse(new NodeVisitor() { SpannableStringBuilder ssb = fromDocument(context, d);
private int qlevel = 0;
private int tlevel = 0;
private int plevel = 0;
private int lindex = 0;
private final List<String> tails = Collections.unmodifiableList(Arrays.asList(
"h1", "h2", "h3", "h4", "h5", "h6", "p", "ol", "ul", "li", "div", "table", "br", "hr"));
public void head(Node node, int depth) {
if (node instanceof TextNode)
if (plevel > 0) {
String[] lines = ((TextNode) node).getWholeText().split("\\r?\\n");
for (String line : lines) {
append(line, true);
newline();
}
} else
append(((TextNode) node).text());
else {
String name = node.nodeName();
if ("li".equals(name) && node.parent() != null)
append("ol".equals(node.parent().nodeName()) ? "-" : "*");
else if ("blockquote".equals(name))
qlevel++;
else if ("pre".equals(name))
plevel++;
}
}
public void tail(Node node, int depth) { for (URLSpan span : ssb.getSpans(0, ssb.length(), URLSpan.class)) {
String name = node.nodeName(); String url = span.getURL();
if ("a".equals(name)) { if (TextUtils.isEmpty(url))
String addr = node.attr("href").toLowerCase(); continue;
if (addr.startsWith("mailto:")) if (url.toLowerCase(Locale.ROOT).startsWith("mailto:"))
addr = addr.substring("mailto:".length()); url = url.substring("mailto:".length());
String text = ((Element) node).text().toLowerCase(); int start = ssb.getSpanStart(span);
if (!text.contains(addr)) int end = ssb.getSpanEnd(span);
append("[" + node.attr("href") + "]"); String text = ssb.subSequence(start, end).toString();
} else if ("img".equals(name)) if (!text.contains(url))
append("[" + node.attr("src") + "]"); ssb.insert(end, "[" + url + "]");
else if ("th".equals(name) || "td".equals(name)) { }
Node next = node.nextSibling();
if (next == null || !("th".equals(next.nodeName()) || "td".equals(next.nodeName())))
newline();
else
append(" ");
} else if ("blockquote".equals(name))
qlevel--;
else if ("pre".equals(name))
plevel--;
if (tails.contains(name) &&
!("br".equals(name) &&
node.nextSibling() == null &&
node.parent() != null && "div".equals(node.parent().nodeName())))
newline();
}
private void append(String text) {
append(text, false);
}
private void append(String text, boolean raw) {
if (tlevel != qlevel) {
newline();
tlevel = qlevel;
}
if (!raw && !"-- ".equals(text)) {
text = text.trim();
if (lindex > 0)
text = " " + text;
}
sb.append(text); for (ImageSpan span : ssb.getSpans(0, ssb.length(), ImageSpan.class)) {
lindex += text.length(); String source = span.getSource();
} if (TextUtils.isEmpty(source))
continue;
int start = ssb.getSpanStart(span);
int end = ssb.getSpanEnd(span);
for (int i = start; i < end; i++)
if (ssb.charAt(i) == '\uFFFC')
ssb.replace(i, i + 1, " ");
ssb.insert(end, "[" + source + "]");
}
private void newline() { for (QuoteSpan span : ssb.getSpans(0, ssb.length(), QuoteSpan.class)) {
lindex = 0; int start = ssb.getSpanStart(span);
sb.append("\n"); int end = ssb.getSpanEnd(span);
for (int i = end - 1; i >= start; i--)
if (ssb.charAt(i) == '\n')
ssb.insert(i + 1, "> ");
if (ssb.charAt(start) != '\n')
ssb.insert(start, "> ");
}
for (int i = 0; i < qlevel; i++) for (BulletSpan span : ssb.getSpans(0, ssb.length(), BulletSpan.class)) {
sb.append("> "); int start = ssb.getSpanStart(span);
} ssb.insert(start, "* ");
}, d); }
sb.append("\n"); for (NumberSpan span : ssb.getSpans(0, ssb.length(), NumberSpan.class)) {
int start = ssb.getSpanStart(span);
ssb.insert(start, "- ");
}
return sb.toString(); return ssb.toString();
} }
static void convertLists(Document document) { static void convertLists(Document document) {
@ -1750,11 +1705,11 @@ public class HtmlHelper {
return false; return false;
} }
static Spanned fromDocument(Context context, @NonNull Document document) { static SpannableStringBuilder fromDocument(Context context, @NonNull Document document) {
return fromDocument(context, document, null, null); return fromDocument(context, document, null, null);
} }
static Spanned fromDocument(Context context, @NonNull Document document, @Nullable Html.ImageGetter imageGetter, @Nullable Html.TagHandler tagHandler) { static SpannableStringBuilder fromDocument(Context context, @NonNull Document document, @Nullable Html.ImageGetter imageGetter, @Nullable Html.TagHandler tagHandler) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean debug = prefs.getBoolean("debug", false); boolean debug = prefs.getBoolean("debug", false);
@ -1818,6 +1773,11 @@ public class HtmlHelper {
tnode = block.get(i); tnode = block.get(i);
text = tnode.getWholeText(); text = tnode.getWholeText();
if ("-- ".equals(text)) {
i++;
continue;
}
// Remove whitespace before/after newlines // Remove whitespace before/after newlines
TRIM_WHITESPACE_NL.matcher(text).replaceAll(" "); TRIM_WHITESPACE_NL.matcher(text).replaceAll(" ");
@ -1900,8 +1860,12 @@ public class HtmlHelper {
String value = param.substring(semi + 1); String value = param.substring(semi + 1);
switch (key) { switch (key) {
case "color": case "color":
int color = Integer.parseInt(value.substring(1), 16) | 0xFF000000; try {
ssb.setSpan(new ForegroundColorSpan(color), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); int color = Integer.parseInt(value.substring(1), 16) | 0xFF000000;
ssb.setSpan(new ForegroundColorSpan(color), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (NumberFormatException ex) {
Log.w(ex);
}
break; break;
case "text-decoration": case "text-decoration":
if ("line-through".equals(value)) if ("line-through".equals(value))
@ -2059,7 +2023,20 @@ public class HtmlHelper {
if (ssb.charAt(i) == '\n') if (ssb.charAt(i) == '\n')
ssb.insert(i, "|"); ssb.insert(i, "|");
return reverseSpans(ssb); Object[] spans = ssb.getSpans(0, ssb.length(), Object.class);
Map<Object, Integer> start = new HashMap<>();
Map<Object, Integer> end = new HashMap<>();
Map<Object, Integer> flags = new HashMap<>();
for (Object span : spans) {
start.put(span, ssb.getSpanStart(span));
end.put(span, ssb.getSpanEnd(span));
flags.put(span, ssb.getSpanFlags(span));
ssb.removeSpan(span);
}
for (int i = spans.length - 1; i >= 0; --i)
ssb.setSpan(spans[i], start.get(spans[i]), end.get(spans[i]), flags.get(spans[i]));
return ssb;
} }
static Spanned fromHtml(@NonNull String html) { static Spanned fromHtml(@NonNull String html) {

@ -501,7 +501,7 @@ public class MessageHelper {
Multipart report = new MimeMultipart("report; report-type=disposition-notification"); Multipart report = new MimeMultipart("report; report-type=disposition-notification");
String html = Helper.readText(message.getFile(context)); String html = Helper.readText(message.getFile(context));
String plainContent = HtmlHelper.getText(html); String plainContent = HtmlHelper.getText(context, html);
BodyPart plainPart = new MimeBodyPart(); BodyPart plainPart = new MimeBodyPart();
plainPart.setContent(plainContent, "text/plain; charset=" + Charset.defaultCharset().name()); plainPart.setContent(plainContent, "text/plain; charset=" + Charset.defaultCharset().name());
@ -612,7 +612,7 @@ public class MessageHelper {
String htmlContent = document.html(); String htmlContent = document.html();
String htmlContentType = "text/html; charset=" + Charset.defaultCharset().name(); String htmlContentType = "text/html; charset=" + Charset.defaultCharset().name();
String plainContent = HtmlHelper.getText(htmlContent); String plainContent = HtmlHelper.getText(context, htmlContent);
String plainContentType = "text/plain; charset=" + Charset.defaultCharset().name(); String plainContentType = "text/plain; charset=" + Charset.defaultCharset().name();
if (format_flowed) { if (format_flowed) {

Loading…
Cancel
Save