From 617a1c8d8f22b048b53131f93784c5c06ee64f7a Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Sat, 18 Aug 2018 16:19:20 +0300 Subject: [PATCH] Add HtmlRenderer asbtraction --- .../ru/noties/markwon/html/api/HtmlTag.java | 10 ++ .../noties/markwon/html/impl/HtmlTagImpl.java | 44 +++++++ .../html/impl/MarkwonHtmlParserImpl.java | 4 +- .../html/impl/MarkwonHtmlParserImplTest.java | 17 +-- markwon/build.gradle | 3 + .../markwon/SpannableConfiguration.java | 96 ++++++++++++---- .../renderer/SpannableMarkdownVisitor.java | 107 ++++++++++-------- .../renderer/html2/MarkwonHtmlRenderer.java | 82 ++++++++++++++ .../html2/MarkwonHtmlRendererImpl.java | 81 +++++++++++++ .../renderer/html2/tag/EmphasisHandler.java | 15 +++ .../renderer/html2/tag/LinkHandler.java | 24 ++++ .../renderer/html2/tag/StrikeHandler.java | 15 +++ .../html2/tag/StrongEmphasisHandler.java | 15 +++ .../renderer/html2/tag/SubScriptHandler.java | 15 +++ .../html2/tag/SuperScriptHandler.java | 15 +++ .../renderer/html2/tag/TagHandler.java | 13 +++ .../renderer/html2/tag/UnderlineHandler.java | 15 +++ 17 files changed, 489 insertions(+), 82 deletions(-) create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRenderer.java create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/MarkwonHtmlRendererImpl.java create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/EmphasisHandler.java create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/LinkHandler.java create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrikeHandler.java create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/StrongEmphasisHandler.java create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SubScriptHandler.java create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/SuperScriptHandler.java create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/TagHandler.java create mode 100644 markwon/src/main/java/ru/noties/markwon/renderer/html2/tag/UnderlineHandler.java 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(); + } +}