diff --git a/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/HtmlTag.java b/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/HtmlTag.java
index b2eb6846..8cd92993 100644
--- a/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/HtmlTag.java
+++ b/markwon-html-parser-api/src/main/java/ru/noties/markwon/html/api/HtmlTag.java
@@ -45,6 +45,16 @@ public interface HtmlTag {
@NonNull
Map attributes();
+ boolean isInline();
+
+ boolean isBlock();
+
+ @NonNull
+ Inline getAsInline();
+
+ @NonNull
+ Block getAsBlock();
+
/**
* Represents really inline HTML tags (unlile commonmark definitions)
*/
diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java b/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java
index 57639e97..01466106 100644
--- a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java
+++ b/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/HtmlTagImpl.java
@@ -79,6 +79,28 @@ abstract class HtmlTagImpl implements HtmlTag {
", attributes=" + attributes +
'}';
}
+
+ @Override
+ public boolean isInline() {
+ return true;
+ }
+
+ @Override
+ public boolean isBlock() {
+ return false;
+ }
+
+ @NonNull
+ @Override
+ public Inline getAsInline() {
+ return this;
+ }
+
+ @NonNull
+ @Override
+ public Block getAsBlock() {
+ throw new ClassCastException("Cannot cast Inline instance to Block");
+ }
}
static class BlockImpl extends HtmlTagImpl implements Block {
@@ -151,6 +173,28 @@ abstract class HtmlTagImpl implements HtmlTag {
return attributes;
}
+ @Override
+ public boolean isInline() {
+ return false;
+ }
+
+ @Override
+ public boolean isBlock() {
+ return true;
+ }
+
+ @NonNull
+ @Override
+ public Inline getAsInline() {
+ throw new ClassCastException("Cannot cast Block instance to Inline");
+ }
+
+ @NonNull
+ @Override
+ public Block getAsBlock() {
+ return this;
+ }
+
@Override
public String toString() {
return "BlockImpl{" +
diff --git a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java b/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java
index abaacaff..4c335f03 100644
--- a/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java
+++ b/markwon-html-parser-impl/src/main/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImpl.java
@@ -2,6 +2,7 @@ package ru.noties.markwon.html.impl;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
import java.io.IOException;
import java.util.ArrayList;
@@ -41,7 +42,8 @@ public class MarkwonHtmlParserImpl extends MarkwonHtmlParser {
}
// https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements
- private static final Set INLINE_TAGS;
+ @VisibleForTesting
+ static final Set INLINE_TAGS;
private static final Set VOID_TAGS;
diff --git a/markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImplTest.java b/markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImplTest.java
index 59cdc3eb..14f33252 100644
--- a/markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImplTest.java
+++ b/markwon-html-parser-impl/src/test/java/ru/noties/markwon/html/impl/MarkwonHtmlParserImplTest.java
@@ -42,22 +42,7 @@ public class MarkwonHtmlParserImplTest {
});
// all inline tags are parsed as ones
- final List tags = Arrays.asList(
- "a", "abbr", "acronym",
- "b", "bdo", "big", "br", "button",
- "cite", "code",
- "dfn",
- "em",
- "i", "img", "input",
- "kbd",
- "label",
- "map",
- "object",
- "q",
- "samp", "script", "select", "small", "span", "strong", "sub", "sup",
- "textarea", "time", "tt",
- "var"
- );
+ final List tags = new ArrayList<>(MarkwonHtmlParserImpl.INLINE_TAGS);
final StringBuilder html = new StringBuilder();
for (String tag : tags) {
diff --git a/markwon/build.gradle b/markwon/build.gradle
index bf49553e..ca7d529f 100644
--- a/markwon/build.gradle
+++ b/markwon/build.gradle
@@ -15,6 +15,9 @@ android {
dependencies {
+ api project(':markwon-html-parser-api')
+ api project(':markwon-html-parser-impl')
+
deps.with {
api it['support-annotations']
api it['commonmark']
diff --git a/markwon/src/main/java/ru/noties/markwon/SpannableConfiguration.java b/markwon/src/main/java/ru/noties/markwon/SpannableConfiguration.java
index a14dac95..4776d9ba 100644
--- a/markwon/src/main/java/ru/noties/markwon/SpannableConfiguration.java
+++ b/markwon/src/main/java/ru/noties/markwon/SpannableConfiguration.java
@@ -3,9 +3,10 @@ package ru.noties.markwon;
import android.content.Context;
import android.support.annotation.NonNull;
+import ru.noties.markwon.html.api.MarkwonHtmlParser;
import ru.noties.markwon.renderer.ImageSizeResolver;
import ru.noties.markwon.renderer.ImageSizeResolverDef;
-import ru.noties.markwon.renderer.html.SpannableHtmlParser;
+import ru.noties.markwon.renderer.html2.MarkwonHtmlRenderer;
import ru.noties.markwon.spans.AsyncDrawable;
import ru.noties.markwon.spans.LinkSpan;
import ru.noties.markwon.spans.SpannableTheme;
@@ -29,11 +30,13 @@ public class SpannableConfiguration {
private final SyntaxHighlight syntaxHighlight;
private final LinkSpan.Resolver linkResolver;
private final UrlProcessor urlProcessor;
- private final SpannableHtmlParser htmlParser;
+ // private final SpannableHtmlParser htmlParser;
private final ImageSizeResolver imageSizeResolver;
private final SpannableFactory factory; // @since 1.1.0
private final boolean softBreakAddsNewLine; // @since 1.1.1
private final boolean trimWhiteSpaceEnd; // @since 2.0.0
+ private final MarkwonHtmlParser htmlParser; // @since 2.0.0
+ private final MarkwonHtmlRenderer htmlRenderer; // @since 2.0.0
private SpannableConfiguration(@NonNull Builder builder) {
this.theme = builder.theme;
@@ -41,11 +44,13 @@ public class SpannableConfiguration {
this.syntaxHighlight = builder.syntaxHighlight;
this.linkResolver = builder.linkResolver;
this.urlProcessor = builder.urlProcessor;
- this.htmlParser = builder.htmlParser;
+// this.htmlParser = builder.htmlParser;
this.imageSizeResolver = builder.imageSizeResolver;
this.factory = builder.factory;
this.softBreakAddsNewLine = builder.softBreakAddsNewLine;
this.trimWhiteSpaceEnd = builder.trimWhiteSpaceEnd;
+ this.htmlParser = builder.htmlParser;
+ this.htmlRenderer = builder.htmlRenderer;
}
@NonNull
@@ -73,10 +78,10 @@ public class SpannableConfiguration {
return urlProcessor;
}
- @NonNull
- public SpannableHtmlParser htmlParser() {
- return htmlParser;
- }
+// @NonNull
+// public SpannableHtmlParser htmlParser() {
+// return htmlParser;
+// }
@NonNull
public ImageSizeResolver imageSizeResolver() {
@@ -104,6 +109,22 @@ public class SpannableConfiguration {
return trimWhiteSpaceEnd;
}
+ /**
+ * @since 2.0.0
+ */
+ @NonNull
+ public MarkwonHtmlParser htmlParser() {
+ return htmlParser;
+ }
+
+ /**
+ * @since 2.0.0
+ */
+ @NonNull
+ public MarkwonHtmlRenderer htmlRenderer() {
+ return htmlRenderer;
+ }
+
@SuppressWarnings("unused")
public static class Builder {
@@ -113,11 +134,13 @@ public class SpannableConfiguration {
private SyntaxHighlight syntaxHighlight;
private LinkSpan.Resolver linkResolver;
private UrlProcessor urlProcessor;
- private SpannableHtmlParser htmlParser;
+ // private SpannableHtmlParser htmlParser;
private ImageSizeResolver imageSizeResolver;
private SpannableFactory factory; // @since 1.1.0
private boolean softBreakAddsNewLine; // @since 1.1.1
private boolean trimWhiteSpaceEnd = true; // @since 2.0.0
+ private MarkwonHtmlParser htmlParser; // @since 2.0.0
+ private MarkwonHtmlRenderer htmlRenderer; // @since 2.0.0
Builder(@NonNull Context context) {
this.context = context;
@@ -153,11 +176,11 @@ public class SpannableConfiguration {
return this;
}
- @NonNull
- public Builder htmlParser(@NonNull SpannableHtmlParser htmlParser) {
- this.htmlParser = htmlParser;
- return this;
- }
+// @NonNull
+// public Builder htmlParser(@NonNull SpannableHtmlParser htmlParser) {
+// this.htmlParser = htmlParser;
+// return this;
+// }
/**
* @since 1.0.1
@@ -202,6 +225,24 @@ public class SpannableConfiguration {
return this;
}
+ /**
+ * @since 2.0.0
+ */
+ @NonNull
+ public Builder htmlParser(@NonNull MarkwonHtmlParser htmlParser) {
+ this.htmlParser = htmlParser;
+ return this;
+ }
+
+ /**
+ * @since 2.0.0
+ */
+ @NonNull
+ public Builder htmlRenderer(@NonNull MarkwonHtmlRenderer htmlRenderer) {
+ this.htmlRenderer = htmlRenderer;
+ return this;
+ }
+
@NonNull
public SpannableConfiguration build() {
@@ -234,16 +275,31 @@ public class SpannableConfiguration {
factory = SpannableFactoryDef.create();
}
+ // @since 2.0.0
if (htmlParser == null) {
- htmlParser = SpannableHtmlParser.create(
- factory,
- theme,
- asyncDrawableLoader,
- urlProcessor,
- linkResolver,
- imageSizeResolver);
+ try {
+ // if impl artifact was excluded -> fallback to no-op implementation
+ htmlParser = ru.noties.markwon.html.impl.MarkwonHtmlParserImpl.create();
+ } catch (Throwable t) {
+ htmlParser = MarkwonHtmlParser.noOp();
+ }
}
+ // @since 2.0.0
+ if (htmlRenderer == null) {
+ htmlRenderer = MarkwonHtmlRenderer.create();
+ }
+
+// if (htmlParser == null) {
+// htmlParser = SpannableHtmlParser.create(
+// factory,
+// theme,
+// asyncDrawableLoader,
+// urlProcessor,
+// linkResolver,
+// imageSizeResolver);
+// }
+
return new SpannableConfiguration(this);
}
}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java b/markwon/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java
index 993c62b0..60f3ae37 100644
--- a/markwon/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java
@@ -43,6 +43,7 @@ import java.util.List;
import ru.noties.markwon.SpannableBuilder;
import ru.noties.markwon.SpannableConfiguration;
import ru.noties.markwon.SpannableFactory;
+import ru.noties.markwon.html.api.MarkwonHtmlParser;
import ru.noties.markwon.renderer.html.SpannableHtmlParser;
import ru.noties.markwon.spans.SpannableTheme;
import ru.noties.markwon.spans.TableRowSpan;
@@ -54,7 +55,8 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
private final SpannableConfiguration configuration;
private final SpannableBuilder builder;
- private final Deque htmlInlineItems;
+ private final MarkwonHtmlParser htmlParser;
+// private final Deque htmlInlineItems;
private final SpannableTheme theme;
private final SpannableFactory factory;
@@ -72,7 +74,8 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
) {
this.configuration = configuration;
this.builder = builder;
- this.htmlInlineItems = new ArrayDeque<>(2);
+ this.htmlParser = configuration.htmlParser();
+// this.htmlInlineItems = new ArrayDeque<>(2);
this.theme = configuration.theme();
this.factory = configuration.factory();
@@ -82,6 +85,8 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
public void visit(Document document) {
super.visit(document);
+ configuration.htmlRenderer().render(configuration, builder, htmlParser);
+
if (configuration.trimWhiteSpaceEnd()) {
builder.trimWhiteSpaceEnd();
}
@@ -445,47 +450,59 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
@Override
public void visit(HtmlBlock htmlBlock) {
- // http://spec.commonmark.org/0.18/#html-blocks
- final Spanned spanned = configuration.htmlParser().getSpanned(null, htmlBlock.getLiteral());
- if (!TextUtils.isEmpty(spanned)) {
- builder.append(spanned);
- }
+// // http://spec.commonmark.org/0.18/#html-blocks
+// final Spanned spanned = configuration.htmlParser().getSpanned(null, htmlBlock.getLiteral());
+// if (!TextUtils.isEmpty(spanned)) {
+// builder.append(spanned);
+// }
+// htmlParser.processFragment(builder, htmlBlock.getLiteral());
+ visitHtml(htmlBlock.getLiteral());
}
@Override
public void visit(HtmlInline htmlInline) {
- final SpannableHtmlParser htmlParser = configuration.htmlParser();
- final SpannableHtmlParser.Tag tag = htmlParser.parseTag(htmlInline.getLiteral());
+ visitHtml(htmlInline.getLiteral());
- if (tag != null) {
+// htmlParser.processFragment(builder, htmlInline.getLiteral());
- final boolean voidTag = tag.voidTag();
- if (!voidTag && tag.opening()) {
- // push in stack
- htmlInlineItems.push(new HtmlInlineItem(tag, builder.length()));
- visitChildren(htmlInline);
- } else {
+// final SpannableHtmlParser htmlParser = configuration.htmlParser();
+// final SpannableHtmlParser.Tag tag = htmlParser.parseTag(htmlInline.getLiteral());
+//
+// if (tag != null) {
+//
+// final boolean voidTag = tag.voidTag();
+// if (!voidTag && tag.opening()) {
+// // push in stack
+// htmlInlineItems.push(new HtmlInlineItem(tag, builder.length()));
+// visitChildren(htmlInline);
+// } else {
+//
+// if (!voidTag) {
+// if (htmlInlineItems.size() > 0) {
+// final HtmlInlineItem item = htmlInlineItems.pop();
+// final Object span = htmlParser.getSpanForTag(item.tag);
+// setSpan(item.start, span);
+// }
+// } else {
+//
+// final Spanned html = htmlParser.getSpanned(tag, htmlInline.getLiteral());
+// if (!TextUtils.isEmpty(html)) {
+// builder.append(html);
+// }
+//
+// }
+// }
+// } else {
+// // todo, should we append just literal?
+//// builder.append(htmlInline.getLiteral());
+// visitChildren(htmlInline);
+// }
+ }
- if (!voidTag) {
- if (htmlInlineItems.size() > 0) {
- final HtmlInlineItem item = htmlInlineItems.pop();
- final Object span = htmlParser.getSpanForTag(item.tag);
- setSpan(item.start, span);
- }
- } else {
-
- final Spanned html = htmlParser.getSpanned(tag, htmlInline.getLiteral());
- if (!TextUtils.isEmpty(html)) {
- builder.append(html);
- }
-
- }
- }
- } else {
- // todo, should we append just literal?
-// builder.append(htmlInline.getLiteral());
- visitChildren(htmlInline);
+ private void visitHtml(@Nullable String html) {
+ if (html != null) {
+ htmlParser.processFragment(builder, html);
}
}
@@ -552,14 +569,14 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
return out;
}
- private static class HtmlInlineItem {
-
- final SpannableHtmlParser.Tag tag;
- final int start;
-
- HtmlInlineItem(SpannableHtmlParser.Tag tag, int start) {
- this.tag = tag;
- this.start = start;
- }
- }
+// private static class HtmlInlineItem {
+//
+// final SpannableHtmlParser.Tag tag;
+// final int start;
+//
+// HtmlInlineItem(SpannableHtmlParser.Tag tag, int start) {
+// this.tag = tag;
+// this.start = start;
+// }
+// }
}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRenderer.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRenderer.java
new file mode 100644
index 00000000..25b529fa
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRenderer.java
@@ -0,0 +1,82 @@
+package ru.noties.markwon.renderer.html2;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import ru.noties.markwon.SpannableBuilder;
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.MarkwonHtmlParser;
+import ru.noties.markwon.renderer.html2.tag.EmphasisHandler;
+import ru.noties.markwon.renderer.html2.tag.LinkHandler;
+import ru.noties.markwon.renderer.html2.tag.StrikeHandler;
+import ru.noties.markwon.renderer.html2.tag.StrongEmphasisHandler;
+import ru.noties.markwon.renderer.html2.tag.SubScriptHandler;
+import ru.noties.markwon.renderer.html2.tag.SuperScriptHandler;
+import ru.noties.markwon.renderer.html2.tag.TagHandler;
+import ru.noties.markwon.renderer.html2.tag.UnderlineHandler;
+
+/**
+ * @since 2.0.0
+ */
+public abstract class MarkwonHtmlRenderer {
+
+ public abstract void render(
+ @NonNull SpannableConfiguration configuration,
+ @NonNull SpannableBuilder builder,
+ @NonNull MarkwonHtmlParser parser
+ );
+
+ @Nullable
+ public abstract TagHandler tagHandler(@NonNull String tagName);
+
+ @NonNull
+ public static MarkwonHtmlRenderer create() {
+
+ final EmphasisHandler emphasisHandler = new EmphasisHandler();
+ final StrongEmphasisHandler strongEmphasisHandler = new StrongEmphasisHandler();
+ final StrikeHandler strikeHandler = new StrikeHandler();
+
+ return builder()
+ .handler("i", emphasisHandler)
+ .handler("em", emphasisHandler)
+ .handler("cite", emphasisHandler)
+ .handler("dfn", emphasisHandler)
+ .handler("b", strongEmphasisHandler)
+ .handler("strong", strongEmphasisHandler)
+ .handler("sup", new SuperScriptHandler())
+ .handler("sub", new SubScriptHandler())
+ .handler("u", new UnderlineHandler())
+ .handler("del", strikeHandler)
+ .handler("s", strikeHandler)
+ .handler("strike", strikeHandler)
+ .handler("a", new LinkHandler())
+ .build();
+ }
+
+ @NonNull
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+
+ private final Map tagHandlers = new HashMap<>(2);
+
+ public Builder handler(@NonNull String tagName, @NonNull TagHandler tagHandler) {
+ tagHandlers.put(tagName.toLowerCase(Locale.US), tagHandler);
+ return this;
+ }
+
+ @NonNull
+ public MarkwonHtmlRenderer build() {
+ return new MarkwonHtmlRendererImpl(
+ Collections.unmodifiableMap(tagHandlers)
+ );
+ }
+ }
+}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRendererImpl.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRendererImpl.java
new file mode 100644
index 00000000..991cb16c
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRendererImpl.java
@@ -0,0 +1,81 @@
+package ru.noties.markwon.renderer.html2;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.Spanned;
+
+import java.util.List;
+import java.util.Map;
+
+import ru.noties.markwon.SpannableBuilder;
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.HtmlTag;
+import ru.noties.markwon.html.api.MarkwonHtmlParser;
+import ru.noties.markwon.renderer.html2.tag.TagHandler;
+
+class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer {
+
+ private final Map tagHandlers;
+
+ MarkwonHtmlRendererImpl(@NonNull Map tagHandlers) {
+ this.tagHandlers = tagHandlers;
+ }
+
+ @Override
+ public void render(
+ @NonNull final SpannableConfiguration configuration,
+ @NonNull final SpannableBuilder builder,
+ @NonNull MarkwonHtmlParser parser) {
+
+ final int length = builder.length();
+
+ parser.flushInlineTags(length, new MarkwonHtmlParser.FlushAction() {
+ @Override
+ public void apply(@NonNull List tags) {
+ TagHandler handler;
+ for (HtmlTag.Inline inline : tags) {
+ handler = tagHandler(inline.name());
+ if (handler != null) {
+ setSpans(builder, handler.getSpans(configuration, inline), inline.start(), inline.end());
+ }
+ }
+ }
+ });
+
+ parser.flushBlockTags(length, new MarkwonHtmlParser.FlushAction() {
+ @Override
+ public void apply(@NonNull List tags) {
+ TagHandler handler;
+ for (HtmlTag.Block block : tags) {
+ handler = tagHandler(block.name());
+ if (handler != null) {
+ setSpans(builder, handler.getSpans(configuration, block), block.start(), block.end());
+ } else {
+ // see if any of children can be handled
+ apply(block.children());
+ }
+ }
+ }
+ });
+
+ parser.reset();
+ }
+
+ @Nullable
+ @Override
+ public TagHandler tagHandler(@NonNull String tagName) {
+ return tagHandlers.get(tagName);
+ }
+
+ private static void setSpans(@NonNull SpannableBuilder builder, @Nullable Object spans, int start, int end) {
+ if (spans != null) {
+ if (spans.getClass().isArray()) {
+ for (Object o : ((Object[]) spans)) {
+ builder.setSpan(o, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ } else {
+ builder.setSpan(spans, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+ }
+}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/EmphasisHandler.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/EmphasisHandler.java
new file mode 100644
index 00000000..a9ee5c70
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/EmphasisHandler.java
@@ -0,0 +1,15 @@
+package ru.noties.markwon.renderer.html2.tag;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.HtmlTag;
+
+public class EmphasisHandler implements TagHandler {
+ @Nullable
+ @Override
+ public Object getSpans(@NonNull SpannableConfiguration configuration, @NonNull HtmlTag tag) {
+ return configuration.factory().emphasis();
+ }
+}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/LinkHandler.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/LinkHandler.java
new file mode 100644
index 00000000..8edfa020
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/LinkHandler.java
@@ -0,0 +1,24 @@
+package ru.noties.markwon.renderer.html2.tag;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.HtmlTag;
+
+public class LinkHandler implements TagHandler {
+ @Nullable
+ @Override
+ public Object getSpans(@NonNull SpannableConfiguration configuration, @NonNull HtmlTag tag) {
+ final String destination = tag.attributes().get("src");
+ if (!TextUtils.isEmpty(destination)) {
+ return configuration.factory().link(
+ configuration.theme(),
+ configuration.urlProcessor().process(destination),
+ configuration.linkResolver()
+ );
+ }
+ return null;
+ }
+}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrikeHandler.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrikeHandler.java
new file mode 100644
index 00000000..574e20d1
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrikeHandler.java
@@ -0,0 +1,15 @@
+package ru.noties.markwon.renderer.html2.tag;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.HtmlTag;
+
+public class StrikeHandler implements TagHandler {
+ @Nullable
+ @Override
+ public Object getSpans(@NonNull SpannableConfiguration configuration, @NonNull HtmlTag tag) {
+ return configuration.factory().strikethrough();
+ }
+}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrongEmphasisHandler.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrongEmphasisHandler.java
new file mode 100644
index 00000000..5b390d1f
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrongEmphasisHandler.java
@@ -0,0 +1,15 @@
+package ru.noties.markwon.renderer.html2.tag;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.HtmlTag;
+
+public class StrongEmphasisHandler implements TagHandler {
+ @Nullable
+ @Override
+ public Object getSpans(@NonNull SpannableConfiguration configuration, @NonNull HtmlTag tag) {
+ return configuration.factory().strongEmphasis();
+ }
+}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SubScriptHandler.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SubScriptHandler.java
new file mode 100644
index 00000000..3e8ea546
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SubScriptHandler.java
@@ -0,0 +1,15 @@
+package ru.noties.markwon.renderer.html2.tag;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.HtmlTag;
+
+public class SubScriptHandler implements TagHandler {
+ @Nullable
+ @Override
+ public Object getSpans(@NonNull SpannableConfiguration configuration, @NonNull HtmlTag tag) {
+ return configuration.factory().subScript(configuration.theme());
+ }
+}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SuperScriptHandler.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SuperScriptHandler.java
new file mode 100644
index 00000000..a05ec567
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SuperScriptHandler.java
@@ -0,0 +1,15 @@
+package ru.noties.markwon.renderer.html2.tag;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.HtmlTag;
+
+public class SuperScriptHandler implements TagHandler {
+ @Nullable
+ @Override
+ public Object getSpans(@NonNull SpannableConfiguration configuration, @NonNull HtmlTag tag) {
+ return configuration.factory().superScript(configuration.theme());
+ }
+}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/TagHandler.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/TagHandler.java
new file mode 100644
index 00000000..e8785616
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/TagHandler.java
@@ -0,0 +1,13 @@
+package ru.noties.markwon.renderer.html2.tag;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.HtmlTag;
+
+public interface TagHandler {
+
+ @Nullable
+ Object getSpans(@NonNull SpannableConfiguration configuration, @NonNull HtmlTag tag);
+}
diff --git a/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/UnderlineHandler.java b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/UnderlineHandler.java
new file mode 100644
index 00000000..12d71d22
--- /dev/null
+++ b/markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/UnderlineHandler.java
@@ -0,0 +1,15 @@
+package ru.noties.markwon.renderer.html2.tag;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import ru.noties.markwon.SpannableConfiguration;
+import ru.noties.markwon.html.api.HtmlTag;
+
+public class UnderlineHandler implements TagHandler {
+ @Nullable
+ @Override
+ public Object getSpans(@NonNull SpannableConfiguration configuration, @NonNull HtmlTag tag) {
+ return configuration.factory().underline();
+ }
+}