mirror of https://github.com/kurisufriend/Clover
parent
5fc8c7b0d7
commit
10ed72775e
@ -0,0 +1,128 @@ |
||||
/* |
||||
* Clover - 4chan browser https://github.com/Floens/Clover/
|
||||
* Copyright (C) 2014 Floens |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
package org.floens.chan.core.site.common; |
||||
|
||||
import android.text.SpannableString; |
||||
|
||||
import org.floens.chan.core.model.Post; |
||||
import org.floens.chan.core.model.PostLinkable; |
||||
import org.floens.chan.ui.theme.Theme; |
||||
import org.jsoup.helper.StringUtil; |
||||
import org.jsoup.nodes.Element; |
||||
import org.jsoup.nodes.Node; |
||||
import org.jsoup.nodes.TextNode; |
||||
import org.jsoup.select.NodeTraversor; |
||||
import org.jsoup.select.NodeVisitor; |
||||
import org.nibor.autolink.LinkExtractor; |
||||
import org.nibor.autolink.LinkSpan; |
||||
import org.nibor.autolink.LinkType; |
||||
|
||||
import java.util.EnumSet; |
||||
|
||||
public class ChanParserHelper { |
||||
private static final LinkExtractor LINK_EXTRACTOR = LinkExtractor.builder() |
||||
.linkTypes(EnumSet.of(LinkType.URL)) |
||||
.build(); |
||||
|
||||
/** |
||||
* Detect links in the given spannable, and create PostLinkables with Type.LINK for the |
||||
* links found onto the spannable. |
||||
* <p> |
||||
* The links are detected with the autolink-java library. |
||||
* |
||||
* @param theme The theme to style the links with |
||||
* @param post The post where the linkables get added to. |
||||
* @param text Text to find links in |
||||
* @param spannable Spannable to set the spans on. |
||||
*/ |
||||
public static void detectLinks(Theme theme, Post.Builder post, String text, SpannableString spannable) { |
||||
final Iterable<LinkSpan> links = LINK_EXTRACTOR.extractLinks(text); |
||||
for (final LinkSpan link : links) { |
||||
final String linkText = text.substring(link.getBeginIndex(), link.getEndIndex()); |
||||
final PostLinkable pl = new PostLinkable(theme, linkText, linkText, PostLinkable.Type.LINK); |
||||
spannable.setSpan(pl, link.getBeginIndex(), link.getEndIndex(), 0); |
||||
post.addLinkable(pl); |
||||
} |
||||
} |
||||
|
||||
// Below code taken from org.jsoup.nodes.Element.text(), but it preserves <br>
|
||||
public static String getNodeTextPreservingLineBreaks(Element node) { |
||||
final StringBuilder accum = new StringBuilder(); |
||||
new NodeTraversor(new NodeVisitor() { |
||||
public void head(Node node, int depth) { |
||||
if (node instanceof TextNode) { |
||||
TextNode textNode = (TextNode) node; |
||||
appendNormalisedText(accum, textNode); |
||||
} else if (node instanceof Element) { |
||||
Element element = (Element) node; |
||||
if (accum.length() > 0 && |
||||
element.isBlock() && |
||||
!lastCharIsWhitespace(accum)) |
||||
accum.append(" "); |
||||
|
||||
if (element.tag().getName().equals("br")) { |
||||
accum.append("\n"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public void tail(Node node, int depth) { |
||||
} |
||||
}).traverse(node); |
||||
return accum.toString().trim(); |
||||
} |
||||
|
||||
// Copied from org.jsoup.nodes.Element.text()
|
||||
private static boolean lastCharIsWhitespace(StringBuilder sb) { |
||||
return sb.length() != 0 && sb.charAt(sb.length() - 1) == ' '; |
||||
} |
||||
|
||||
// Copied from org.jsoup.nodes.Element.text()
|
||||
private static void appendNormalisedText(StringBuilder accum, TextNode textNode) { |
||||
String text = textNode.getWholeText(); |
||||
|
||||
if (!preserveWhitespace(textNode.parent())) { |
||||
text = normaliseWhitespace(text); |
||||
if (lastCharIsWhitespace(accum)) |
||||
text = stripLeadingWhitespace(text); |
||||
} |
||||
accum.append(text); |
||||
} |
||||
|
||||
// Copied from org.jsoup.nodes.Element.text()
|
||||
private static String normaliseWhitespace(String text) { |
||||
text = StringUtil.normaliseWhitespace(text); |
||||
return text; |
||||
} |
||||
|
||||
// Copied from org.jsoup.nodes.Element.text()
|
||||
private static String stripLeadingWhitespace(String text) { |
||||
return text.replaceFirst("^\\s+", ""); |
||||
} |
||||
|
||||
// Copied from org.jsoup.nodes.Element.text()
|
||||
private static boolean preserveWhitespace(Node node) { |
||||
// looks only at this element and one level up, to prevent recursion & needless stack searches
|
||||
if (node != null && node instanceof Element) { |
||||
Element element = (Element) node; |
||||
return element.tag().preserveWhitespace() || |
||||
element.parent() != null && element.parent().tag().preserveWhitespace(); |
||||
} |
||||
return false; |
||||
} |
||||
} |
Loading…
Reference in new issue