Htmlpublic class Html extends Object This class processes HTML strings into displayable styled text.
Not all HTML tags are supported. |
Constructors Summary |
---|
private Html()
|
Methods Summary |
---|
public static java.lang.String | escapeHtml(java.lang.CharSequence text)Returns an HTML escaped representation of the given plain text.
StringBuilder out = new StringBuilder();
withinStyle(out, text, 0, text.length());
return out.toString();
| public static Spanned | fromHtml(java.lang.String source)Returns displayable styled text from the provided HTML string.
Any <img> tags in the HTML will display as a generic
replacement image which your program can then go through and
replace with real images.
This uses TagSoup to handle real HTML, including all of the brokenness found in the wild.
return fromHtml(source, null, null);
| public static Spanned | fromHtml(java.lang.String source, android.text.Html$ImageGetter imageGetter, android.text.Html$TagHandler tagHandler)Returns displayable styled text from the provided HTML string.
Any <img> tags in the HTML will use the specified ImageGetter
to request a representation of the image (use null if you don't
want this) and the specified TagHandler to handle unknown tags
(specify null if you don't want this).
This uses TagSoup to handle real HTML, including all of the brokenness found in the wild.
Parser parser = new Parser();
try {
parser.setProperty(Parser.schemaProperty, HtmlParser.schema);
} catch (org.xml.sax.SAXNotRecognizedException e) {
// Should not happen.
throw new RuntimeException(e);
} catch (org.xml.sax.SAXNotSupportedException e) {
// Should not happen.
throw new RuntimeException(e);
}
HtmlToSpannedConverter converter =
new HtmlToSpannedConverter(source, imageGetter, tagHandler,
parser);
return converter.convert();
| private static java.lang.String | getOpenParaTagWithDirection(Spanned text, int start, int end)
final int len = end - start;
final byte[] levels = ArrayUtils.newUnpaddedByteArray(len);
final char[] buffer = TextUtils.obtain(len);
TextUtils.getChars(text, start, end, buffer, 0);
int paraDir = AndroidBidi.bidi(Layout.DIR_REQUEST_DEFAULT_LTR, buffer, levels, len,
false /* no info */);
switch(paraDir) {
case Layout.DIR_RIGHT_TO_LEFT:
return "<p dir=\"rtl\">";
case Layout.DIR_LEFT_TO_RIGHT:
default:
return "<p dir=\"ltr\">";
}
| public static java.lang.String | toHtml(Spanned text)Returns an HTML representation of the provided Spanned text.
StringBuilder out = new StringBuilder();
withinHtml(out, text);
return out.toString();
| private static void | withinBlockquote(java.lang.StringBuilder out, Spanned text, int start, int end)
out.append(getOpenParaTagWithDirection(text, start, end));
int next;
for (int i = start; i < end; i = next) {
next = TextUtils.indexOf(text, '\n", i, end);
if (next < 0) {
next = end;
}
int nl = 0;
while (next < end && text.charAt(next) == '\n") {
nl++;
next++;
}
withinParagraph(out, text, i, next - nl, nl, next == end);
}
out.append("</p>\n");
| private static void | withinDiv(java.lang.StringBuilder out, Spanned text, int start, int end)
int next;
for (int i = start; i < end; i = next) {
next = text.nextSpanTransition(i, end, QuoteSpan.class);
QuoteSpan[] quotes = text.getSpans(i, next, QuoteSpan.class);
for (QuoteSpan quote : quotes) {
out.append("<blockquote>");
}
withinBlockquote(out, text, i, next);
for (QuoteSpan quote : quotes) {
out.append("</blockquote>\n");
}
}
| private static void | withinHtml(java.lang.StringBuilder out, Spanned text)
int len = text.length();
int next;
for (int i = 0; i < text.length(); i = next) {
next = text.nextSpanTransition(i, len, ParagraphStyle.class);
ParagraphStyle[] style = text.getSpans(i, next, ParagraphStyle.class);
String elements = " ";
boolean needDiv = false;
for(int j = 0; j < style.length; j++) {
if (style[j] instanceof AlignmentSpan) {
Layout.Alignment align =
((AlignmentSpan) style[j]).getAlignment();
needDiv = true;
if (align == Layout.Alignment.ALIGN_CENTER) {
elements = "align=\"center\" " + elements;
} else if (align == Layout.Alignment.ALIGN_OPPOSITE) {
elements = "align=\"right\" " + elements;
} else {
elements = "align=\"left\" " + elements;
}
}
}
if (needDiv) {
out.append("<div ").append(elements).append(">");
}
withinDiv(out, text, i, next);
if (needDiv) {
out.append("</div>");
}
}
| private static void | withinParagraph(java.lang.StringBuilder out, Spanned text, int start, int end, int nl, boolean last)
int next;
for (int i = start; i < end; i = next) {
next = text.nextSpanTransition(i, end, CharacterStyle.class);
CharacterStyle[] style = text.getSpans(i, next,
CharacterStyle.class);
for (int j = 0; j < style.length; j++) {
if (style[j] instanceof StyleSpan) {
int s = ((StyleSpan) style[j]).getStyle();
if ((s & Typeface.BOLD) != 0) {
out.append("<b>");
}
if ((s & Typeface.ITALIC) != 0) {
out.append("<i>");
}
}
if (style[j] instanceof TypefaceSpan) {
String s = ((TypefaceSpan) style[j]).getFamily();
if (s.equals("monospace")) {
out.append("<tt>");
}
}
if (style[j] instanceof SuperscriptSpan) {
out.append("<sup>");
}
if (style[j] instanceof SubscriptSpan) {
out.append("<sub>");
}
if (style[j] instanceof UnderlineSpan) {
out.append("<u>");
}
if (style[j] instanceof StrikethroughSpan) {
out.append("<strike>");
}
if (style[j] instanceof URLSpan) {
out.append("<a href=\"");
out.append(((URLSpan) style[j]).getURL());
out.append("\">");
}
if (style[j] instanceof ImageSpan) {
out.append("<img src=\"");
out.append(((ImageSpan) style[j]).getSource());
out.append("\">");
// Don't output the dummy character underlying the image.
i = next;
}
if (style[j] instanceof AbsoluteSizeSpan) {
out.append("<font size =\"");
out.append(((AbsoluteSizeSpan) style[j]).getSize() / 6);
out.append("\">");
}
if (style[j] instanceof ForegroundColorSpan) {
out.append("<font color =\"#");
String color = Integer.toHexString(((ForegroundColorSpan)
style[j]).getForegroundColor() + 0x01000000);
while (color.length() < 6) {
color = "0" + color;
}
out.append(color);
out.append("\">");
}
}
withinStyle(out, text, i, next);
for (int j = style.length - 1; j >= 0; j--) {
if (style[j] instanceof ForegroundColorSpan) {
out.append("</font>");
}
if (style[j] instanceof AbsoluteSizeSpan) {
out.append("</font>");
}
if (style[j] instanceof URLSpan) {
out.append("</a>");
}
if (style[j] instanceof StrikethroughSpan) {
out.append("</strike>");
}
if (style[j] instanceof UnderlineSpan) {
out.append("</u>");
}
if (style[j] instanceof SubscriptSpan) {
out.append("</sub>");
}
if (style[j] instanceof SuperscriptSpan) {
out.append("</sup>");
}
if (style[j] instanceof TypefaceSpan) {
String s = ((TypefaceSpan) style[j]).getFamily();
if (s.equals("monospace")) {
out.append("</tt>");
}
}
if (style[j] instanceof StyleSpan) {
int s = ((StyleSpan) style[j]).getStyle();
if ((s & Typeface.BOLD) != 0) {
out.append("</b>");
}
if ((s & Typeface.ITALIC) != 0) {
out.append("</i>");
}
}
}
}
String p = last ? "" : "</p>\n" + getOpenParaTagWithDirection(text, start, end);
if (nl == 1) {
out.append("<br>\n");
} else if (nl == 2) {
out.append(p);
} else {
for (int i = 2; i < nl; i++) {
out.append("<br>");
}
out.append(p);
}
| private static void | withinStyle(java.lang.StringBuilder out, java.lang.CharSequence text, int start, int end)
for (int i = start; i < end; i++) {
char c = text.charAt(i);
if (c == '<") {
out.append("<");
} else if (c == '>") {
out.append(">");
} else if (c == '&") {
out.append("&");
} else if (c >= 0xD800 && c <= 0xDFFF) {
if (c < 0xDC00 && i + 1 < end) {
char d = text.charAt(i + 1);
if (d >= 0xDC00 && d <= 0xDFFF) {
i++;
int codepoint = 0x010000 | (int) c - 0xD800 << 10 | (int) d - 0xDC00;
out.append("").append(codepoint).append(";");
}
}
} else if (c > 0x7E || c < ' ") {
out.append("").append((int) c).append(";");
} else if (c == ' ") {
while (i + 1 < end && text.charAt(i + 1) == ' ") {
out.append(" ");
i++;
}
out.append(' ");
} else {
out.append(c);
}
}
|
|