Html helper failsafe

This commit is contained in:
M66B 2020-08-12 22:21:55 +02:00
parent 993b30f4fa
commit bddf5760b3
1 changed files with 139 additions and 134 deletions

View File

@ -2026,145 +2026,150 @@ public class HtmlHelper {
} }
// Apply element // Apply element
String tag = element.tagName(); try {
int semi = tag.indexOf(':'); String tag = element.tagName();
if (semi >= 0) int semi = tag.indexOf(':');
tag = tag.substring(semi + 1); if (semi >= 0)
switch (tag) { tag = tag.substring(semi + 1);
case "a":
String href = element.attr("href");
if (!TextUtils.isEmpty(href))
ssb.setSpan(new URLSpan(href), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "body":
// Do nothing
break;
case "big":
ssb.setSpan(new RelativeSizeSpan(FONT_LARGE), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "blockquote":
if (start == 0 || ssb.charAt(start - 1) != '\n')
ssb.insert(start++, "\n");
if (ssb.length() == 0 || ssb.charAt(ssb.length() - 1) != '\n')
ssb.append("\n");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) switch (tag) {
ssb.setSpan(new QuoteSpan(colorPrimary), start, ssb.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); case "a":
else String href = element.attr("href");
ssb.setSpan(new QuoteSpan(colorPrimary, dp3, dp6), start, ssb.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); if (!TextUtils.isEmpty(href))
break; ssb.setSpan(new URLSpan(href), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
case "br": break;
newline(ssb.length()); case "body":
break; // Do nothing
case "div": // compose break;
case "p": // compose case "big":
newline(ssb.length()); ssb.setSpan(new RelativeSizeSpan(FONT_LARGE), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
newline(ssb.length()); break;
break; case "blockquote":
case "i": if (start == 0 || ssb.charAt(start - 1) != '\n')
case "em": ssb.insert(start++, "\n");
ssb.setSpan(new StyleSpan(Typeface.ITALIC), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); if (ssb.length() == 0 || ssb.charAt(ssb.length() - 1) != '\n')
break; ssb.append("\n");
case "font":
// Do nothing
break;
case "h1":
case "h2":
case "h3":
case "h4":
case "h5":
case "h6":
int level = element.tagName().charAt(1) - '1';
ssb.setSpan(new RelativeSizeSpan(HEADING_SIZES[level]), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new StyleSpan(Typeface.BOLD), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
newline(start);
newline(ssb.length());
break;
case "hr":
ssb.append("\n" + LINE + "\n");
float stroke = context.getResources().getDisplayMetrics().density;
ssb.setSpan(new LineSpan(colorSeparator, stroke),
ssb.length() - 1 - LINE.length(), ssb.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "img":
String src = element.attr("src");
Drawable d = (imageGetter == null
? context.getDrawable(R.drawable.baseline_broken_image_24)
: imageGetter.getDrawable(src));
ssb.insert(start, "\uFFFC"); // Object replacement character
ssb.setSpan(new ImageSpan(d, src), start, start + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "li":
if (start == 0 || ssb.charAt(start - 1) != '\n')
ssb.insert(start++, "\n");
if (ssb.length() == 0 || ssb.charAt(ssb.length() - 1) != '\n')
ssb.append("\n");
Element parent = element.parent();
if (parent == null || "ul".equals(parent.tagName()))
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
ssb.setSpan(new BulletSpan(dp6, colorAccent), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.setSpan(new QuoteSpan(colorPrimary), start, ssb.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
else else
ssb.setSpan(new BulletSpan(dp6, colorAccent, dp3), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.setSpan(new QuoteSpan(colorPrimary, dp3, dp6), start, ssb.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
else { break;
int index = 0; case "br":
for (Node child : parent.childNodes()) { newline(ssb.length());
if (child instanceof Element && break;
child.nodeName().equals(element.tagName())) { case "div": // compose
index++; case "p": // compose
if (child == element) newline(ssb.length());
break; newline(ssb.length());
} break;
} case "i":
case "em":
ssb.setSpan(new StyleSpan(Typeface.ITALIC), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "font":
// Do nothing
break;
case "h1":
case "h2":
case "h3":
case "h4":
case "h5":
case "h6":
int level = element.tagName().charAt(1) - '1';
ssb.setSpan(new RelativeSizeSpan(HEADING_SIZES[level]), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new StyleSpan(Typeface.BOLD), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
newline(start);
newline(ssb.length());
break;
case "hr":
ssb.append("\n" + LINE + "\n");
float stroke = context.getResources().getDisplayMetrics().density;
ssb.setSpan(new LineSpan(colorSeparator, stroke),
ssb.length() - 1 - LINE.length(), ssb.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "img":
String src = element.attr("src");
Drawable d = (imageGetter == null
? context.getDrawable(R.drawable.baseline_broken_image_24)
: imageGetter.getDrawable(src));
ssb.insert(start, "\uFFFC"); // Object replacement character
ssb.setSpan(new ImageSpan(d, src), start, start + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "li":
if (start == 0 || ssb.charAt(start - 1) != '\n')
ssb.insert(start++, "\n");
if (ssb.length() == 0 || ssb.charAt(ssb.length() - 1) != '\n')
ssb.append("\n");
float textSize = Helper.getTextSize(context, 0); Element parent = element.parent();
ssb.setSpan(new NumberSpan(dp6, colorAccent, textSize, index), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); if (parent == null || "ul".equals(parent.tagName()))
} if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
break; ssb.setSpan(new BulletSpan(dp6, colorAccent), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
case "ol": else
case "ul": ssb.setSpan(new BulletSpan(dp6, colorAccent, dp3), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
int llevel = 0; else {
Element lparent = element.parent(); int index = 0;
while (lparent != null) { for (Node child : parent.childNodes()) {
if (lparent.tagName().equals(element.tagName())) if (child instanceof Element &&
llevel++; child.nodeName().equals(element.tagName())) {
lparent = lparent.parent(); index++;
} if (child == element)
if (llevel > 0) break;
ssb.setSpan(new LeadingMarginSpan.Standard(llevel * dp24), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); }
break; }
case "small":
ssb.setSpan(new RelativeSizeSpan(FONT_SMALL), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); float textSize = Helper.getTextSize(context, 0);
break; ssb.setSpan(new NumberSpan(dp6, colorAccent, textSize, index), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
case "span": }
// Do nothing break;
break; case "ol":
case "sub": case "ul":
ssb.setSpan(new SubscriptSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); int llevel = 0;
ssb.setSpan(new RelativeSizeSpan(FONT_SMALL), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Element lparent = element.parent();
break; while (lparent != null) {
case "sup": if (lparent.tagName().equals(element.tagName()))
ssb.setSpan(new SuperscriptSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); llevel++;
ssb.setSpan(new RelativeSizeSpan(FONT_SMALL), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); lparent = lparent.parent();
break; }
case "b": if (llevel > 0)
case "strong": ssb.setSpan(new LeadingMarginSpan.Standard(llevel * dp24), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new StyleSpan(Typeface.BOLD), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); break;
break; case "small":
case "s": ssb.setSpan(new RelativeSizeSpan(FONT_SMALL), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
case "del": break;
case "strike": case "span":
ssb.setSpan(new StrikethroughSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // Do nothing
break; break;
case "tt": case "sub":
ssb.setSpan(new TypefaceSpan("monospace"), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.setSpan(new SubscriptSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break; ssb.setSpan(new RelativeSizeSpan(FONT_SMALL), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
case "u": break;
ssb.setSpan(new UnderlineSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); case "sup":
break; ssb.setSpan(new SuperscriptSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
default: ssb.setSpan(new RelativeSizeSpan(FONT_SMALL), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
if (warn) break;
Log.e("Unknown tag=" + element.tagName()); case "b":
case "strong":
ssb.setSpan(new StyleSpan(Typeface.BOLD), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "s":
case "del":
case "strike":
ssb.setSpan(new StrikethroughSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "tt":
ssb.setSpan(new TypefaceSpan("monospace"), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case "u":
ssb.setSpan(new UnderlineSpan(), start, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
default:
if (warn)
Log.e("Unknown tag=" + element.tagName());
}
} catch (Throwable ex) {
Log.e(ex);
} }
} }
} }