configure the commentparser in the site.

refactor-toolbar
Floens 8 years ago
parent 489ca21877
commit 64b2f15e38
  1. 15
      Clover/app/src/main/java/org/floens/chan/core/site/common/CommonSite.java
  2. 4
      Clover/app/src/main/java/org/floens/chan/core/site/common/FutabaChanReader.java
  3. 48
      Clover/app/src/main/java/org/floens/chan/core/site/parser/CommentParser.java
  4. 72
      Clover/app/src/main/java/org/floens/chan/core/site/parser/CommentParserHelper.java
  5. 13
      Clover/app/src/main/java/org/floens/chan/core/site/parser/StyleRule.java
  6. 30
      Clover/app/src/main/java/org/floens/chan/core/site/sites/vichan/ViChan.java
  7. 34
      Clover/app/src/main/java/org/floens/chan/core/site/sites/vichan/ViChanCommentParser.java

@ -40,6 +40,7 @@ import org.floens.chan.core.site.http.LoginRequest;
import org.floens.chan.core.site.http.Reply;
import org.floens.chan.core.site.http.ReplyResponse;
import org.floens.chan.core.site.parser.ChanReader;
import org.floens.chan.core.site.parser.CommentParser;
import org.floens.chan.core.site.parser.PostParser;
import java.io.IOException;
@ -62,9 +63,10 @@ public abstract class CommonSite extends SiteBase {
private CommonEndpoints endpoints;
private CommonActions actions;
private CommonApi api;
private CommonParser parser;
private CommonRequestModifier requestModifier;
private PostParser postParser;
@Override
public void initialize(int id, SiteConfig config, JsonSettings userSettings) {
super.initialize(id, config, userSettings);
@ -102,7 +104,7 @@ public abstract class CommonSite extends SiteBase {
throw new NullPointerException("setApi not called");
}
if (parser == null) {
if (postParser == null) {
throw new NullPointerException("setParser not called");
}
@ -147,8 +149,8 @@ public abstract class CommonSite extends SiteBase {
this.api = api;
}
public void setParser(CommonParser parser) {
this.parser = parser;
public void setParser(CommentParser commentParser) {
postParser = new DefaultPostParser(commentParser);
}
public void setRequestModifier(CommonRequestModifier requestModifier) {
@ -407,13 +409,10 @@ public abstract class CommonSite extends SiteBase {
public abstract class CommonApi implements ChanReader {
@Override
public PostParser getParser() {
return parser;
return postParser;
}
}
public abstract class CommonParser implements PostParser {
}
public abstract class CommonRequestModifier implements SiteRequestModifier {
@Override
public void modifyHttpCall(HttpCall httpCall, Request.Builder requestBuilder) {

@ -26,7 +26,9 @@ public class FutabaChanReader implements ChanReader {
private final PostParser postParser;
public FutabaChanReader() {
this.postParser = new DefaultPostParser(new CommentParser());
CommentParser commentParser = new CommentParser();
commentParser.addDefaultRules();
this.postParser = new DefaultPostParser(commentParser);
}
public FutabaChanReader(PostParser postParser) {

@ -36,7 +36,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -51,16 +50,18 @@ public class CommentParser {
private Pattern fullQuotePattern = Pattern.compile("/(\\w+)/\\w+/(\\d+)#p(\\d+)");
private Pattern quotePattern = Pattern.compile(".*#p(\\d+)");
private Pattern colorPattern = Pattern.compile("color:#([0-9a-fA-F]*)");
private Pattern colorPattern = Pattern.compile("color:#([0-9a-fA-F]+)");
private Map<String, List<StyleRule>> rules = new HashMap<>();
public CommentParser() {
// Required tags.
rule(tagRule("p"));
rule(tagRule("div"));
rule(tagRule("br").just("\n"));
}
public void addDefaultRules() {
rule(tagRule("a").action(this::handleAnchor));
rule(tagRule("span").cssClass("deadlink").color(StyleRule.Color.QUOTE).strikeThrough());
@ -73,7 +74,11 @@ public class CommentParser {
rule(tagRule("s").link(PostLinkable.Type.SPOILER));
rule(tagRule("strong").color(StyleRule.Color.QUOTE).bold());
rule(tagRule("strong").bold());
rule(tagRule("b").bold());
rule(tagRule("i").italic());
rule(tagRule("em").italic());
rule(tagRule("pre").cssClass("prettyprint").monospace().size(sp(12f)));
}
@ -173,26 +178,14 @@ public class CommentParser {
Post.Builder builder,
CharSequence text,
Element span) {
Set<String> classes = span.classNames();
if (classes.contains("fortune")) {
// html looks like <span class="fortune" style="color:#0893e1"><br><br><b>Your fortune:</b>
String style = span.attr("style");
if (!TextUtils.isEmpty(style)) {
style = style.replace(" ", "");
Matcher matcher = colorPattern.matcher(style);
int hexColor = 0xff0000;
if (matcher.find()) {
String group = matcher.group(1);
if (!TextUtils.isEmpty(group)) {
try {
hexColor = Integer.parseInt(group, 16);
} catch (NumberFormatException ignored) {
}
}
}
// html looks like <span class="fortune" style="color:#0893e1"><br><br><b>Your fortune:</b>
String style = span.attr("style");
if (!TextUtils.isEmpty(style)) {
style = style.replace(" ", "");
Matcher matcher = colorPattern.matcher(style);
if (matcher.find()) {
int hexColor = Integer.parseInt(matcher.group(1), 16);
if (hexColor >= 0 && hexColor <= 0xffffff) {
text = span(text, new ForegroundColorSpanHashed(0xff000000 + hexColor),
new StyleSpan(Typeface.BOLD));
@ -203,13 +196,6 @@ public class CommentParser {
return text;
}
public CharSequence handleParagraph(Theme theme,
Post.Builder post,
CharSequence text,
Element span) {
return text;
}
public CharSequence handleTable(Theme theme,
PostParser.Callback callback,
Post.Builder builder,

@ -23,12 +23,6 @@ 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;
@ -61,70 +55,4 @@ public class CommentParserHelper {
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;
}
}

@ -55,6 +55,7 @@ public class StyleRule {
private Color color = null;
private boolean strikeThrough = false;
private boolean bold = false;
private boolean italic = false;
private boolean monospace = false;
private int size = 0;
@ -120,6 +121,12 @@ public class StyleRule {
return this;
}
public StyleRule italic() {
italic = true;
return this;
}
public StyleRule monospace() {
monospace = true;
@ -202,8 +209,12 @@ public class StyleRule {
spansToApply.add(new StrikethroughSpan());
}
if (bold) {
if (bold && italic) {
spansToApply.add(new StyleSpan(Typeface.BOLD_ITALIC));
} else if (bold) {
spansToApply.add(new StyleSpan(Typeface.BOLD));
} else if (italic) {
spansToApply.add(new StyleSpan(Typeface.ITALIC));
}
if (monospace) {

@ -8,19 +8,17 @@ import org.floens.chan.core.model.PostHttpIcon;
import org.floens.chan.core.model.PostImage;
import org.floens.chan.core.model.orm.Board;
import org.floens.chan.core.model.orm.Loadable;
import org.floens.chan.core.site.SiteAuthentication;
import org.floens.chan.core.site.Site;
import org.floens.chan.core.site.SiteAuthentication;
import org.floens.chan.core.site.SiteEndpoints;
import org.floens.chan.core.site.SiteIcon;
import org.floens.chan.core.site.parser.ChanReader;
import org.floens.chan.core.site.parser.ChanReaderProcessingQueue;
import org.floens.chan.core.site.common.DefaultPostParser;
import org.floens.chan.core.site.common.FutabaChanReader;
import org.floens.chan.core.site.common.CommonSite;
import org.floens.chan.core.site.common.MultipartHttpCall;
import org.floens.chan.core.site.http.Reply;
import org.floens.chan.core.site.http.ReplyResponse;
import org.floens.chan.core.site.common.CommonSite;
import org.floens.chan.ui.theme.Theme;
import org.floens.chan.core.site.parser.ChanReaderProcessingQueue;
import org.floens.chan.core.site.parser.CommentParser;
import org.floens.chan.core.site.parser.StyleRule;
import org.jsoup.Jsoup;
import org.jsoup.parser.Parser;
@ -103,11 +101,6 @@ public class ViChan extends CommonSite {
private static final String TAG = "ViChan";
@Override
public ChanReader chanReader() {
return new FutabaChanReader(new DefaultPostParser(new ViChanCommentParser()));
}
@Override
public void setup() {
setName("8chan");
@ -244,12 +237,13 @@ public class ViChan extends CommonSite {
setApi(new ViChanApi());
setParser(new CommonParser() {
@Override
public Post parse(Theme theme, Post.Builder builder, Callback callback) {
return null;
}
});
CommentParser commentParser = new CommentParser();
commentParser.addDefaultRules();
commentParser.setQuotePattern(Pattern.compile(".*#(\\d+)"));
commentParser.setFullQuotePattern(Pattern.compile("/(\\w+)/\\w+/(\\d+)\\.html#(\\d+)"));
commentParser.rule(StyleRule.tagRule("p").cssClass("quote").color(StyleRule.Color.INLINE_QUOTE).linkify());
setParser(commentParser);
}
private class ViChanApi extends CommonApi {

@ -1,34 +0,0 @@
/*
* 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.sites.vichan;
import org.floens.chan.core.site.parser.CommentParser;
import org.floens.chan.core.site.parser.StyleRule;
import java.util.regex.Pattern;
import static org.floens.chan.core.site.parser.StyleRule.tagRule;
public class ViChanCommentParser extends CommentParser {
public ViChanCommentParser() {
setQuotePattern(Pattern.compile(".*#(\\d+)"));
setFullQuotePattern(Pattern.compile("/(\\w+)/\\w+/(\\d+)\\.html#(\\d+)"));
rule(tagRule("p").cssClass("quote").color(StyleRule.Color.INLINE_QUOTE).linkify());
}
}
Loading…
Cancel
Save