diff --git a/library/src/main/java/ru/noties/markwon/SpannableConfiguration.java b/library/src/main/java/ru/noties/markwon/SpannableConfiguration.java index 73c8e57b..dda590f5 100644 --- a/library/src/main/java/ru/noties/markwon/SpannableConfiguration.java +++ b/library/src/main/java/ru/noties/markwon/SpannableConfiguration.java @@ -31,7 +31,7 @@ public class SpannableConfiguration { private final UrlProcessor urlProcessor; private final SpannableHtmlParser htmlParser; private final ImageSizeResolver imageSizeResolver; - private final SpannableFactory spannableFactory; // @since 1.1.0 + private final SpannableFactory factory; // @since 1.1.0 private SpannableConfiguration(@NonNull Builder builder) { this.theme = builder.theme; @@ -41,7 +41,7 @@ public class SpannableConfiguration { this.urlProcessor = builder.urlProcessor; this.htmlParser = builder.htmlParser; this.imageSizeResolver = builder.imageSizeResolver; - this.spannableFactory = builder.spannableFactory; + this.factory = builder.factory; } @NonNull @@ -81,7 +81,7 @@ public class SpannableConfiguration { @NonNull public SpannableFactory factory() { - return spannableFactory; + return factory; } @SuppressWarnings("unused") @@ -95,7 +95,7 @@ public class SpannableConfiguration { private UrlProcessor urlProcessor; private SpannableHtmlParser htmlParser; private ImageSizeResolver imageSizeResolver; - private SpannableFactory spannableFactory; + private SpannableFactory factory; Builder(@NonNull Context context) { this.context = context; @@ -150,8 +150,8 @@ public class SpannableConfiguration { * @since 1.1.0 */ @NonNull - public Builder spannableFactory(@NonNull SpannableFactory spannableFactory) { - this.spannableFactory = spannableFactory; + public Builder factory(@NonNull SpannableFactory factory) { + this.factory = factory; return this; } @@ -183,12 +183,18 @@ public class SpannableConfiguration { } // @since 1.1.0 - if (spannableFactory == null) { - spannableFactory = SpannableFactoryDef.create(); + if (factory == null) { + factory = SpannableFactoryDef.create(); } if (htmlParser == null) { - htmlParser = SpannableHtmlParser.create(theme, asyncDrawableLoader, urlProcessor, linkResolver, imageSizeResolver); + htmlParser = SpannableHtmlParser.create( + factory, + theme, + asyncDrawableLoader, + urlProcessor, + linkResolver, + imageSizeResolver); } return new SpannableConfiguration(this); diff --git a/library/src/main/java/ru/noties/markwon/SpannableFactory.java b/library/src/main/java/ru/noties/markwon/SpannableFactory.java index a9dbcd04..4cd6b947 100644 --- a/library/src/main/java/ru/noties/markwon/SpannableFactory.java +++ b/library/src/main/java/ru/noties/markwon/SpannableFactory.java @@ -70,4 +70,16 @@ public interface SpannableFactory { @NonNull SpannableTheme theme, @NonNull String destination, @NonNull LinkSpan.Resolver resolver); + + // Currently used by HTML parser + @Nullable + Object superScript(@NonNull SpannableTheme theme); + + // Currently used by HTML parser + @Nullable + Object subScript(@NonNull SpannableTheme theme); + + // Currently used by HTML parser + @Nullable + Object underline(); } diff --git a/library/src/main/java/ru/noties/markwon/SpannableFactoryDef.java b/library/src/main/java/ru/noties/markwon/SpannableFactoryDef.java index 2ff060e3..a7068f9b 100644 --- a/library/src/main/java/ru/noties/markwon/SpannableFactoryDef.java +++ b/library/src/main/java/ru/noties/markwon/SpannableFactoryDef.java @@ -3,6 +3,7 @@ package ru.noties.markwon; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.style.StrikethroughSpan; +import android.text.style.UnderlineSpan; import java.util.List; @@ -19,6 +20,8 @@ import ru.noties.markwon.spans.LinkSpan; import ru.noties.markwon.spans.OrderedListItemSpan; import ru.noties.markwon.spans.SpannableTheme; import ru.noties.markwon.spans.StrongEmphasisSpan; +import ru.noties.markwon.spans.SubScriptSpan; +import ru.noties.markwon.spans.SuperScriptSpan; import ru.noties.markwon.spans.TableRowSpan; import ru.noties.markwon.spans.TaskListSpan; import ru.noties.markwon.spans.ThematicBreakSpan; @@ -118,4 +121,21 @@ public class SpannableFactoryDef implements SpannableFactory { public Object link(@NonNull SpannableTheme theme, @NonNull String destination, @NonNull LinkSpan.Resolver resolver) { return new LinkSpan(theme, destination, resolver); } + + @Nullable + @Override + public Object superScript(@NonNull SpannableTheme theme) { + return new SuperScriptSpan(theme); + } + + @Override + public Object subScript(@NonNull SpannableTheme theme) { + return new SubScriptSpan(theme); + } + + @Nullable + @Override + public Object underline() { + return new UnderlineSpan(); + } } diff --git a/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java b/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java index 3898f5d0..82745e50 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java +++ b/library/src/main/java/ru/noties/markwon/renderer/SpannableMarkdownVisitor.java @@ -4,7 +4,6 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.Spanned; import android.text.TextUtils; -import android.text.style.StrikethroughSpan; import org.commonmark.ext.gfm.strikethrough.Strikethrough; import org.commonmark.ext.gfm.tables.TableBody; @@ -44,20 +43,8 @@ import ru.noties.markwon.SpannableBuilder; import ru.noties.markwon.SpannableConfiguration; import ru.noties.markwon.SpannableFactory; import ru.noties.markwon.renderer.html.SpannableHtmlParser; -import ru.noties.markwon.spans.AsyncDrawable; -import ru.noties.markwon.spans.AsyncDrawableSpan; -import ru.noties.markwon.spans.BlockQuoteSpan; -import ru.noties.markwon.spans.BulletListItemSpan; -import ru.noties.markwon.spans.CodeSpan; -import ru.noties.markwon.spans.EmphasisSpan; -import ru.noties.markwon.spans.HeadingSpan; -import ru.noties.markwon.spans.LinkSpan; -import ru.noties.markwon.spans.OrderedListItemSpan; import ru.noties.markwon.spans.SpannableTheme; -import ru.noties.markwon.spans.StrongEmphasisSpan; import ru.noties.markwon.spans.TableRowSpan; -import ru.noties.markwon.spans.TaskListSpan; -import ru.noties.markwon.spans.ThematicBreakSpan; import ru.noties.markwon.tasklist.TaskListBlock; import ru.noties.markwon.tasklist.TaskListItem; @@ -467,9 +454,7 @@ public class SpannableMarkdownVisitor extends AbstractVisitor { if (htmlInlineItems.size() > 0) { final HtmlInlineItem item = htmlInlineItems.pop(); final Object span = htmlParser.getSpanForTag(item.tag); - if (span != null) { - setSpan(item.start, span); - } + setSpan(item.start, span); } } else { @@ -501,7 +486,7 @@ public class SpannableMarkdownVisitor extends AbstractVisitor { final int length = builder.length(); if (span.getClass().isArray()) { - for (Object o: ((Object[]) span)) { + for (Object o : ((Object[]) span)) { builder.setSpan(o, start, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } else { diff --git a/library/src/main/java/ru/noties/markwon/renderer/html/BoldProvider.java b/library/src/main/java/ru/noties/markwon/renderer/html/BoldProvider.java index 7613b8b4..fbd42fc4 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/html/BoldProvider.java +++ b/library/src/main/java/ru/noties/markwon/renderer/html/BoldProvider.java @@ -2,12 +2,21 @@ package ru.noties.markwon.renderer.html; import android.support.annotation.NonNull; -import ru.noties.markwon.spans.StrongEmphasisSpan; +import ru.noties.markwon.SpannableFactory; class BoldProvider implements SpannableHtmlParser.SpanProvider { + private final SpannableFactory factory; + + /** + * @since 1.1.0 + */ + BoldProvider(@NonNull SpannableFactory factory) { + this.factory = factory; + } + @Override public Object provide(@NonNull SpannableHtmlParser.Tag tag) { - return new StrongEmphasisSpan(); + return factory.strongEmphasis(); } } diff --git a/library/src/main/java/ru/noties/markwon/renderer/html/ImageProviderImpl.java b/library/src/main/java/ru/noties/markwon/renderer/html/ImageProviderImpl.java index 1d5968b7..10f62c41 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/html/ImageProviderImpl.java +++ b/library/src/main/java/ru/noties/markwon/renderer/html/ImageProviderImpl.java @@ -10,26 +10,29 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import ru.noties.markwon.SpannableFactory; import ru.noties.markwon.UrlProcessor; import ru.noties.markwon.renderer.ImageSize; import ru.noties.markwon.renderer.ImageSizeResolver; import ru.noties.markwon.spans.AsyncDrawable; -import ru.noties.markwon.spans.AsyncDrawableSpan; import ru.noties.markwon.spans.SpannableTheme; class ImageProviderImpl implements SpannableHtmlParser.ImageProvider { + private final SpannableFactory factory; private final SpannableTheme theme; private final AsyncDrawable.Loader loader; private final UrlProcessor urlProcessor; private final ImageSizeResolver imageSizeResolver; ImageProviderImpl( + @NonNull SpannableFactory factory, @NonNull SpannableTheme theme, @NonNull AsyncDrawable.Loader loader, @NonNull UrlProcessor urlProcessor, @NonNull ImageSizeResolver imageSizeResolver ) { + this.factory = factory; this.theme = theme; this.loader = loader; this.urlProcessor = urlProcessor; @@ -56,11 +59,26 @@ class ImageProviderImpl implements SpannableHtmlParser.ImageProvider { replacement = "\uFFFC"; } - final AsyncDrawable drawable = new AsyncDrawable(destination, loader, imageSizeResolver, parseImageSize(attributes)); - final AsyncDrawableSpan span = new AsyncDrawableSpan(theme, drawable); + final Object span = factory.image( + theme, + destination, + loader, + imageSizeResolver, + parseImageSize(attributes), + false); final SpannableString string = new SpannableString(replacement); - string.setSpan(span, 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + if (span != null) { + final int length = string.length(); + if (span.getClass().isArray()) { + for (Object o : ((Object[]) span)) { + string.setSpan(o, 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } else { + string.setSpan(span, 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } spanned = string; } else { diff --git a/library/src/main/java/ru/noties/markwon/renderer/html/ItalicsProvider.java b/library/src/main/java/ru/noties/markwon/renderer/html/ItalicsProvider.java index 3fd7f068..51f33ff7 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/html/ItalicsProvider.java +++ b/library/src/main/java/ru/noties/markwon/renderer/html/ItalicsProvider.java @@ -2,12 +2,21 @@ package ru.noties.markwon.renderer.html; import android.support.annotation.NonNull; -import ru.noties.markwon.spans.EmphasisSpan; +import ru.noties.markwon.SpannableFactory; class ItalicsProvider implements SpannableHtmlParser.SpanProvider { + private final SpannableFactory factory; + + /** + * @since 1.1.0 + */ + ItalicsProvider(@NonNull SpannableFactory factory) { + this.factory = factory; + } + @Override public Object provide(@NonNull SpannableHtmlParser.Tag tag) { - return new EmphasisSpan(); + return factory.emphasis(); } } diff --git a/library/src/main/java/ru/noties/markwon/renderer/html/LinkProvider.java b/library/src/main/java/ru/noties/markwon/renderer/html/LinkProvider.java index b85456f6..d15668bd 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/html/LinkProvider.java +++ b/library/src/main/java/ru/noties/markwon/renderer/html/LinkProvider.java @@ -5,20 +5,24 @@ import android.text.TextUtils; import java.util.Map; +import ru.noties.markwon.SpannableFactory; import ru.noties.markwon.UrlProcessor; import ru.noties.markwon.spans.LinkSpan; import ru.noties.markwon.spans.SpannableTheme; class LinkProvider implements SpannableHtmlParser.SpanProvider { + private final SpannableFactory factory; private final SpannableTheme theme; private final UrlProcessor urlProcessor; private final LinkSpan.Resolver resolver; LinkProvider( + @NonNull SpannableFactory factory, @NonNull SpannableTheme theme, @NonNull UrlProcessor urlProcessor, @NonNull LinkSpan.Resolver resolver) { + this.factory = factory; this.theme = theme; this.urlProcessor = urlProcessor; this.resolver = resolver; @@ -34,7 +38,7 @@ class LinkProvider implements SpannableHtmlParser.SpanProvider { if (!TextUtils.isEmpty(href)) { final String destination = urlProcessor.process(href); - span = new LinkSpan(theme, destination, resolver); + span = factory.link(theme, destination, resolver); } else { span = null; diff --git a/library/src/main/java/ru/noties/markwon/renderer/html/SpannableHtmlParser.java b/library/src/main/java/ru/noties/markwon/renderer/html/SpannableHtmlParser.java index 3d7236a9..2604337e 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/html/SpannableHtmlParser.java +++ b/library/src/main/java/ru/noties/markwon/renderer/html/SpannableHtmlParser.java @@ -11,6 +11,7 @@ import java.util.HashMap; import java.util.Map; import ru.noties.markwon.LinkResolverDef; +import ru.noties.markwon.SpannableFactory; import ru.noties.markwon.UrlProcessor; import ru.noties.markwon.UrlProcessorNoOp; import ru.noties.markwon.renderer.ImageSizeResolver; @@ -22,53 +23,68 @@ import ru.noties.markwon.spans.SpannableTheme; @SuppressWarnings("WeakerAccess") public class SpannableHtmlParser { - // creates default parser - @NonNull - public static SpannableHtmlParser create( - @NonNull SpannableTheme theme, - @NonNull AsyncDrawable.Loader loader - ) { - return builderWithDefaults(theme, loader, null, null, null) - .build(); - } +// // creates default parser +// @NonNull +// public static SpannableHtmlParser create( +// @NonNull SpannableTheme theme, +// @NonNull AsyncDrawable.Loader loader +// ) { +// return builderWithDefaults(theme, loader, null, null, null) +// .build(); +// } +// +// /** +// * @since 1.0.1 +// */ +// @NonNull +// public static SpannableHtmlParser create( +// @NonNull SpannableTheme theme, +// @NonNull AsyncDrawable.Loader loader, +// @NonNull ImageSizeResolver imageSizeResolver +// ) { +// return builderWithDefaults(theme, loader, null, null, imageSizeResolver) +// .build(); +// } +// +// @NonNull +// public static SpannableHtmlParser create( +// @NonNull SpannableTheme theme, +// @NonNull AsyncDrawable.Loader loader, +// @NonNull UrlProcessor urlProcessor, +// @NonNull LinkSpan.Resolver resolver +// ) { +// return builderWithDefaults(theme, loader, urlProcessor, resolver, null) +// .build(); +// } + +// /** +// * @since 1.0.1 +// */ +// @NonNull +// public static SpannableHtmlParser create( +// @NonNull SpannableTheme theme, +// @NonNull AsyncDrawable.Loader loader, +// @NonNull UrlProcessor urlProcessor, +// @NonNull LinkSpan.Resolver resolver, +// @NonNull ImageSizeResolver imageSizeResolver +// ) { +// return builderWithDefaults(theme, loader, urlProcessor, resolver, imageSizeResolver) +// .build(); +// } /** - * @since 1.0.1 - */ - @NonNull - public static SpannableHtmlParser create( - @NonNull SpannableTheme theme, - @NonNull AsyncDrawable.Loader loader, - @NonNull ImageSizeResolver imageSizeResolver - ) { - return builderWithDefaults(theme, loader, null, null, imageSizeResolver) - .build(); - } - - @NonNull - public static SpannableHtmlParser create( - @NonNull SpannableTheme theme, - @NonNull AsyncDrawable.Loader loader, - @NonNull UrlProcessor urlProcessor, - @NonNull LinkSpan.Resolver resolver - ) { - return builderWithDefaults(theme, loader, urlProcessor, resolver, null) - .build(); - } - - /** - * @since 1.0.1 + * @since 1.1.0 */ @NonNull public static SpannableHtmlParser create( + @NonNull SpannableFactory factory, @NonNull SpannableTheme theme, @NonNull AsyncDrawable.Loader loader, @NonNull UrlProcessor urlProcessor, @NonNull LinkSpan.Resolver resolver, @NonNull ImageSizeResolver imageSizeResolver ) { - return builderWithDefaults(theme, loader, urlProcessor, resolver, imageSizeResolver) - .build(); + return builderWithDefaults(factory, theme, loader, urlProcessor, resolver, imageSizeResolver).build(); } @NonNull @@ -76,16 +92,27 @@ public class SpannableHtmlParser { return new Builder(); } + /** + * @since 1.1.0 + */ @NonNull - public static Builder builderWithDefaults(@NonNull SpannableTheme theme) { - return builderWithDefaults(theme, null, null, null, null); + public static Builder builderWithDefaults(@NonNull SpannableFactory factory, @NonNull SpannableTheme theme) { + return builderWithDefaults( + factory, + theme, + null, + null, + null, + null); } /** * Updated in 1.0.1: added imageSizeResolverArgument + * Updated in 1.1.0: add SpannableFactory */ @NonNull public static Builder builderWithDefaults( + @NonNull SpannableFactory factory, @NonNull SpannableTheme theme, @Nullable AsyncDrawable.Loader asyncDrawableLoader, @Nullable UrlProcessor urlProcessor, @@ -101,9 +128,9 @@ public class SpannableHtmlParser { resolver = new LinkResolverDef(); } - final BoldProvider boldProvider = new BoldProvider(); - final ItalicsProvider italicsProvider = new ItalicsProvider(); - final StrikeProvider strikeProvider = new StrikeProvider(); + final BoldProvider boldProvider = new BoldProvider(factory); + final ItalicsProvider italicsProvider = new ItalicsProvider(factory); + final StrikeProvider strikeProvider = new StrikeProvider(factory); final ImageProvider imageProvider; if (asyncDrawableLoader != null) { @@ -112,7 +139,12 @@ public class SpannableHtmlParser { imageSizeResolver = new ImageSizeResolverDef(); } - imageProvider = new ImageProviderImpl(theme, asyncDrawableLoader, urlProcessor, imageSizeResolver); + imageProvider = new ImageProviderImpl( + factory, + theme, + asyncDrawableLoader, + urlProcessor, + imageSizeResolver); } else { imageProvider = null; } @@ -124,13 +156,13 @@ public class SpannableHtmlParser { .simpleTag("em", italicsProvider) .simpleTag("cite", italicsProvider) .simpleTag("dfn", italicsProvider) - .simpleTag("sup", new SuperScriptProvider(theme)) - .simpleTag("sub", new SubScriptProvider(theme)) - .simpleTag("u", new UnderlineProvider()) + .simpleTag("sup", new SuperScriptProvider(factory, theme)) + .simpleTag("sub", new SubScriptProvider(factory, theme)) + .simpleTag("u", new UnderlineProvider(factory)) .simpleTag("del", strikeProvider) .simpleTag("s", strikeProvider) .simpleTag("strike", strikeProvider) - .simpleTag("a", new LinkProvider(theme, urlProcessor, resolver)) + .simpleTag("a", new LinkProvider(factory, theme, urlProcessor, resolver)) .imageProvider(imageProvider); } diff --git a/library/src/main/java/ru/noties/markwon/renderer/html/StrikeProvider.java b/library/src/main/java/ru/noties/markwon/renderer/html/StrikeProvider.java index df01f9e6..c2d3fbc8 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/html/StrikeProvider.java +++ b/library/src/main/java/ru/noties/markwon/renderer/html/StrikeProvider.java @@ -1,11 +1,22 @@ package ru.noties.markwon.renderer.html; import android.support.annotation.NonNull; -import android.text.style.StrikethroughSpan; + +import ru.noties.markwon.SpannableFactory; class StrikeProvider implements SpannableHtmlParser.SpanProvider { + + private final SpannableFactory factory; + + /** + * @since 1.1.0 + */ + StrikeProvider(@NonNull SpannableFactory factory) { + this.factory = factory; + } + @Override public Object provide(@NonNull SpannableHtmlParser.Tag tag) { - return new StrikethroughSpan(); + return factory.strikethrough(); } } diff --git a/library/src/main/java/ru/noties/markwon/renderer/html/SubScriptProvider.java b/library/src/main/java/ru/noties/markwon/renderer/html/SubScriptProvider.java index 920ff01e..451ae299 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/html/SubScriptProvider.java +++ b/library/src/main/java/ru/noties/markwon/renderer/html/SubScriptProvider.java @@ -2,19 +2,21 @@ package ru.noties.markwon.renderer.html; import android.support.annotation.NonNull; +import ru.noties.markwon.SpannableFactory; import ru.noties.markwon.spans.SpannableTheme; -import ru.noties.markwon.spans.SubScriptSpan; class SubScriptProvider implements SpannableHtmlParser.SpanProvider { + private final SpannableFactory factory; private final SpannableTheme theme; - public SubScriptProvider(SpannableTheme theme) { + SubScriptProvider(@NonNull SpannableFactory factory, @NonNull SpannableTheme theme) { + this.factory = factory; this.theme = theme; } @Override public Object provide(@NonNull SpannableHtmlParser.Tag tag) { - return new SubScriptSpan(theme); + return factory.subScript(theme); } } diff --git a/library/src/main/java/ru/noties/markwon/renderer/html/SuperScriptProvider.java b/library/src/main/java/ru/noties/markwon/renderer/html/SuperScriptProvider.java index 4faf9078..db747e3d 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/html/SuperScriptProvider.java +++ b/library/src/main/java/ru/noties/markwon/renderer/html/SuperScriptProvider.java @@ -2,19 +2,21 @@ package ru.noties.markwon.renderer.html; import android.support.annotation.NonNull; +import ru.noties.markwon.SpannableFactory; import ru.noties.markwon.spans.SpannableTheme; -import ru.noties.markwon.spans.SuperScriptSpan; class SuperScriptProvider implements SpannableHtmlParser.SpanProvider { + private final SpannableFactory factory; private final SpannableTheme theme; - SuperScriptProvider(SpannableTheme theme) { + SuperScriptProvider(@NonNull SpannableFactory factory, @NonNull SpannableTheme theme) { + this.factory = factory; this.theme = theme; } @Override public Object provide(@NonNull SpannableHtmlParser.Tag tag) { - return new SuperScriptSpan(theme); + return factory.superScript(theme); } } diff --git a/library/src/main/java/ru/noties/markwon/renderer/html/UnderlineProvider.java b/library/src/main/java/ru/noties/markwon/renderer/html/UnderlineProvider.java index 38acc73c..f44fc913 100644 --- a/library/src/main/java/ru/noties/markwon/renderer/html/UnderlineProvider.java +++ b/library/src/main/java/ru/noties/markwon/renderer/html/UnderlineProvider.java @@ -1,12 +1,22 @@ package ru.noties.markwon.renderer.html; import android.support.annotation.NonNull; -import android.text.style.UnderlineSpan; + +import ru.noties.markwon.SpannableFactory; class UnderlineProvider implements SpannableHtmlParser.SpanProvider { + private final SpannableFactory factory; + + /** + * @since 1.1.0 + */ + UnderlineProvider(@NonNull SpannableFactory factory) { + this.factory = factory; + } + @Override public Object provide(@NonNull SpannableHtmlParser.Tag tag) { - return new UnderlineSpan(); + return factory.underline(); } }