package kr.kdev.dg1s.biowiki.util;
import android.content.Context;
import android.content.res.Resources;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.QuoteSpan;
import org.apache.commons.lang.StringEscapeUtils;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Created by nbradbury on 7/9/13.
*/
public class HtmlUtils {
/*
* removes html from the passed string - relies on Html.fromHtml which handles invalid HTML,
* but it's very slow, so avoid using this where performance is important
*/
public static String stripHtml(final String text) {
if (TextUtils.isEmpty(text))
return "";
return Html.fromHtml(text).toString().trim();
}
/*
* this is much faster than stripHtml() but should only be used when we know the html is valid
* since the regex will be unpredictable with invalid html
*/
public static String fastStripHtml(String text) {
if (TextUtils.isEmpty(text))
return text;
// insert a line break before P tags unless the only one is at the start
if (text.lastIndexOf("<p") > 0)
text = text.replaceAll("<p(.|\n)*?>", "\n<p>");
// convert BR tags to line breaks
if (text.contains("<br"))
text = text.replaceAll("<br(.|\n)*?>", "\n");
// use regex to strip tags, then convert entities in the result
return fastUnescapeHtml(text.replaceAll("<(.|\n)*?>", "").trim());
}
/*
* convert html entities to actual Unicode characters - relies on commons apache lang
*/
public static String fastUnescapeHtml(final String text) {
if (text == null || !text.contains("&"))
return text;
return StringEscapeUtils.unescapeHtml(text);
}
/*
* converts an R.color.xxx resource to an HTML hex color
*/
public static String colorResToHtmlColor(Context context, int resId) {
try {
return String.format("#%06X", 0xFFFFFF & context.getResources().getColor(resId));
} catch (Resources.NotFoundException e) {
return "#000000";
}
}
/*
* remove <script>..</script> blocks from the passed string - added to project after noticing
* comments on posts that use the "Sociable" plugin ( http://wordpress.org/plugins/sociable/ )
* may have a script block which contains <!--//--> followed by a CDATA section followed by <!]]>,
* all of which will show up if we don't strip it here (example: http://cl.ly/image/0J0N3z3h1i04 )
* first seen at http://houseofgeekery.com/2013/11/03/13-terrible-x-men-we-wont-see-in-the-movies/
*/
public static String stripScript(final String text) {
if (text == null)
return null;
StringBuilder sb = new StringBuilder(text);
int start = sb.indexOf("<script");
while (start > -1) {
int end = sb.indexOf("</script>", start);
if (end == -1)
return sb.toString();
sb.delete(start, end + 9);
start = sb.indexOf("<script", start);
}
return sb.toString();
}
/**
* an alternative to Html.fromHtml() supporting <ul>, <ol>, <blockquote> tags and replacing Emoticons with Emojis
*/
public static SpannableStringBuilder fromHtml(String source) {
SpannableStringBuilder html;
try {
html = (SpannableStringBuilder) Html.fromHtml(source, null, new BWHtmlTagHandler());
} catch (RuntimeException runtimeException) {
// In case our tag handler fails
html = (SpannableStringBuilder) Html.fromHtml(source, null, null);
// Log the exception and text that produces the error
try {
JSONObject additionalData = new JSONObject();
additionalData.put("input_text", source);
BWMobileStatsUtil.trackException(runtimeException, BWMobileStatsUtil.StatsPropertyExceptionNoteParsing,
additionalData);
} catch (JSONException jsonException) {
AppLog.e(AppLog.T.UTILS, jsonException);
}
}
Emoticons.replaceEmoticonsWithEmoji(html);
QuoteSpan spans[] = html.getSpans(0, html.length(), QuoteSpan.class);
for (QuoteSpan span : spans) {
html.setSpan(new BWHtml.WPQuoteSpan(), html.getSpanStart(span), html.getSpanEnd(span), html.getSpanFlags(
span));
html.removeSpan(span);
}
return html;
}
}