registryImpl test
This commit is contained in:
parent
173425ed53
commit
a2a5857f06
@ -8,4 +8,5 @@
|
|||||||
* removed priority
|
* removed priority
|
||||||
* images-plugin moved to standalone again
|
* images-plugin moved to standalone again
|
||||||
* removed MarkwonPlugin#configureHtmlRenderer -> now part of HtmlPlugin
|
* removed MarkwonPlugin#configureHtmlRenderer -> now part of HtmlPlugin
|
||||||
* TagHandler now has `supportedTags()` method
|
* TagHandler now has `supportedTags()` method
|
||||||
|
* html is moved completely to html-plugin
|
@ -13,27 +13,24 @@ import java.util.concurrent.Future;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import io.noties.debug.Debug;
|
||||||
import io.noties.markwon.AbstractMarkwonPlugin;
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||||
import io.noties.markwon.Markwon;
|
import io.noties.markwon.Markwon;
|
||||||
import io.noties.markwon.MarkwonConfiguration;
|
import io.noties.markwon.MarkwonConfiguration;
|
||||||
|
import io.noties.markwon.app.gif.GifAwarePlugin;
|
||||||
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
|
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
|
||||||
import io.noties.markwon.ext.tables.TablePlugin;
|
import io.noties.markwon.ext.tables.TablePlugin;
|
||||||
import io.noties.markwon.ext.tasklist.TaskListPlugin;
|
import io.noties.markwon.ext.tasklist.TaskListPlugin;
|
||||||
import io.noties.markwon.app.gif.GifAwarePlugin;
|
|
||||||
import io.noties.markwon.html.HtmlPlugin;
|
import io.noties.markwon.html.HtmlPlugin;
|
||||||
import io.noties.markwon.image.ImagesPlugin;
|
import io.noties.markwon.image.ImagesPlugin;
|
||||||
import io.noties.markwon.image.data.DataUriSchemeHandler;
|
|
||||||
import io.noties.markwon.image.file.FileSchemeHandler;
|
import io.noties.markwon.image.file.FileSchemeHandler;
|
||||||
import io.noties.markwon.image.gif.GifMediaDecoder;
|
|
||||||
import io.noties.markwon.image.network.OkHttpNetworkSchemeHandler;
|
import io.noties.markwon.image.network.OkHttpNetworkSchemeHandler;
|
||||||
import io.noties.markwon.image.svg.SvgMediaDecoder;
|
|
||||||
import io.noties.markwon.syntax.Prism4jTheme;
|
import io.noties.markwon.syntax.Prism4jTheme;
|
||||||
import io.noties.markwon.syntax.Prism4jThemeDarkula;
|
import io.noties.markwon.syntax.Prism4jThemeDarkula;
|
||||||
import io.noties.markwon.syntax.Prism4jThemeDefault;
|
import io.noties.markwon.syntax.Prism4jThemeDefault;
|
||||||
import io.noties.markwon.syntax.SyntaxHighlightPlugin;
|
import io.noties.markwon.syntax.SyntaxHighlightPlugin;
|
||||||
import io.noties.markwon.urlprocessor.UrlProcessor;
|
import io.noties.markwon.urlprocessor.UrlProcessor;
|
||||||
import io.noties.markwon.urlprocessor.UrlProcessorRelativeToAbsolute;
|
import io.noties.markwon.urlprocessor.UrlProcessorRelativeToAbsolute;
|
||||||
import io.noties.debug.Debug;
|
|
||||||
import ru.noties.prism4j.Prism4j;
|
import ru.noties.prism4j.Prism4j;
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
@ -102,12 +99,12 @@ public class MarkdownRenderer {
|
|||||||
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
.usePlugin(ImagesPlugin.create(new ImagesPlugin.ImagesConfigure() {
|
||||||
@Override
|
@Override
|
||||||
public void configureImages(@NonNull ImagesPlugin plugin) {
|
public void configureImages(@NonNull ImagesPlugin plugin) {
|
||||||
|
// data uri scheme handler is added automatically
|
||||||
|
// SVG & GIF will be added if required dependencies are present in the classpath
|
||||||
|
// default-media-decoder is also added automatically
|
||||||
plugin
|
plugin
|
||||||
.addSchemeHandler(DataUriSchemeHandler.create())
|
|
||||||
.addSchemeHandler(OkHttpNetworkSchemeHandler.create())
|
.addSchemeHandler(OkHttpNetworkSchemeHandler.create())
|
||||||
.addSchemeHandler(FileSchemeHandler.createWithAssets(context.getAssets()))
|
.addSchemeHandler(FileSchemeHandler.createWithAssets(context.getAssets()));
|
||||||
.addMediaDecoder(GifMediaDecoder.create(false))
|
|
||||||
.addMediaDecoder(SvgMediaDecoder.create());
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.usePlugin(SyntaxHighlightPlugin.create(prism4j, prism4jTheme))
|
.usePlugin(SyntaxHighlightPlugin.create(prism4j, prism4jTheme))
|
||||||
|
@ -5,7 +5,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||||
classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
|
classpath 'com.github.ben-manes:gradle-versions-plugin:0.21.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,18 +2,14 @@ package io.noties.markwon;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.annotation.VisibleForTesting;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.commonmark.parser.Parser;
|
import org.commonmark.parser.Parser;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import io.noties.markwon.core.MarkwonTheme;
|
import io.noties.markwon.core.MarkwonTheme;
|
||||||
|
|
||||||
@ -106,109 +102,8 @@ class MarkwonBuilderImpl implements Markwon.Builder {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
@NonNull
|
@NonNull
|
||||||
static List<MarkwonPlugin> preparePlugins(@NonNull List<MarkwonPlugin> plugins) {
|
private static List<MarkwonPlugin> preparePlugins(@NonNull List<MarkwonPlugin> plugins) {
|
||||||
return new RegistryImpl(plugins).process();
|
return new RegistryImpl(plugins).process();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
|
||||||
private static class RegistryImpl implements MarkwonPlugin.Registry {
|
|
||||||
|
|
||||||
private final List<MarkwonPlugin> origin;
|
|
||||||
private final List<MarkwonPlugin> plugins;
|
|
||||||
private final Set<MarkwonPlugin> pending;
|
|
||||||
|
|
||||||
RegistryImpl(@NonNull List<MarkwonPlugin> origin) {
|
|
||||||
this.origin = origin;
|
|
||||||
this.plugins = new ArrayList<>(origin.size());
|
|
||||||
this.pending = new HashSet<>(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public <P extends MarkwonPlugin> P require(@NonNull Class<P> plugin) {
|
|
||||||
return get(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <P extends MarkwonPlugin> void require(
|
|
||||||
@NonNull Class<P> plugin,
|
|
||||||
@NonNull MarkwonPlugin.Action<? super P> action) {
|
|
||||||
action.apply(get(plugin));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
List<MarkwonPlugin> process() {
|
|
||||||
for (MarkwonPlugin plugin : origin) {
|
|
||||||
configure(plugin);
|
|
||||||
}
|
|
||||||
return plugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configure(@NonNull MarkwonPlugin plugin) {
|
|
||||||
|
|
||||||
// important -> check if it's in plugins
|
|
||||||
// if it is -> no need to configure (already configured)
|
|
||||||
|
|
||||||
if (!plugins.contains(plugin)) {
|
|
||||||
|
|
||||||
if (pending.contains(plugin)) {
|
|
||||||
throw new IllegalStateException("Cyclic dependency chain found: " + pending);
|
|
||||||
}
|
|
||||||
|
|
||||||
// start tracking plugins that are pending for configuration
|
|
||||||
pending.add(plugin);
|
|
||||||
|
|
||||||
plugin.configure(this);
|
|
||||||
|
|
||||||
// stop pending tracking
|
|
||||||
pending.remove(plugin);
|
|
||||||
|
|
||||||
// check again if it's included (a child might've configured it already)
|
|
||||||
// add to out-collection if not already present
|
|
||||||
// this is a bit different from `find` method as it does check for exact instance
|
|
||||||
// and not a sub-type
|
|
||||||
if (!plugins.contains(plugin)) {
|
|
||||||
plugins.add(plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private <P extends MarkwonPlugin> P get(@NonNull Class<P> type) {
|
|
||||||
|
|
||||||
// check if present already in plugins
|
|
||||||
// find in origin, if not found -> throw, else add to out-plugins
|
|
||||||
|
|
||||||
P plugin = find(plugins, type);
|
|
||||||
|
|
||||||
if (plugin == null) {
|
|
||||||
|
|
||||||
plugin = find(origin, type);
|
|
||||||
|
|
||||||
if (plugin == null) {
|
|
||||||
throw new IllegalStateException("Requested plugin is not added: " +
|
|
||||||
"" + type.getName() + ", plugins: " + origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
configure(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
return plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static <P extends MarkwonPlugin> P find(
|
|
||||||
@NonNull List<MarkwonPlugin> plugins,
|
|
||||||
@NonNull Class<P> type) {
|
|
||||||
for (MarkwonPlugin plugin : plugins) {
|
|
||||||
if (type.isAssignableFrom(plugin.getClass())) {
|
|
||||||
//noinspection unchecked
|
|
||||||
return (P) plugin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,6 @@ import android.support.annotation.NonNull;
|
|||||||
|
|
||||||
import io.noties.markwon.core.MarkwonTheme;
|
import io.noties.markwon.core.MarkwonTheme;
|
||||||
import io.noties.markwon.core.spans.LinkSpan;
|
import io.noties.markwon.core.spans.LinkSpan;
|
||||||
import io.noties.markwon.html.MarkwonHtmlParser;
|
|
||||||
import io.noties.markwon.html.MarkwonHtmlRenderer;
|
|
||||||
import io.noties.markwon.image.AsyncDrawableLoader;
|
import io.noties.markwon.image.AsyncDrawableLoader;
|
||||||
import io.noties.markwon.image.ImageSizeResolver;
|
import io.noties.markwon.image.ImageSizeResolver;
|
||||||
import io.noties.markwon.image.ImageSizeResolverDef;
|
import io.noties.markwon.image.ImageSizeResolverDef;
|
||||||
@ -31,8 +29,6 @@ public class MarkwonConfiguration {
|
|||||||
private final LinkSpan.Resolver linkResolver;
|
private final LinkSpan.Resolver linkResolver;
|
||||||
private final UrlProcessor urlProcessor;
|
private final UrlProcessor urlProcessor;
|
||||||
private final ImageSizeResolver imageSizeResolver;
|
private final ImageSizeResolver imageSizeResolver;
|
||||||
private final MarkwonHtmlParser htmlParser;
|
|
||||||
private final MarkwonHtmlRenderer htmlRenderer;
|
|
||||||
|
|
||||||
// @since 3.0.0
|
// @since 3.0.0
|
||||||
private final MarkwonSpansFactory spansFactory;
|
private final MarkwonSpansFactory spansFactory;
|
||||||
@ -45,8 +41,6 @@ public class MarkwonConfiguration {
|
|||||||
this.urlProcessor = builder.urlProcessor;
|
this.urlProcessor = builder.urlProcessor;
|
||||||
this.imageSizeResolver = builder.imageSizeResolver;
|
this.imageSizeResolver = builder.imageSizeResolver;
|
||||||
this.spansFactory = builder.spansFactory;
|
this.spansFactory = builder.spansFactory;
|
||||||
this.htmlParser = builder.htmlParser;
|
|
||||||
this.htmlRenderer = builder.htmlRenderer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -79,16 +73,6 @@ public class MarkwonConfiguration {
|
|||||||
return imageSizeResolver;
|
return imageSizeResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public MarkwonHtmlParser htmlParser() {
|
|
||||||
return htmlParser;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public MarkwonHtmlRenderer htmlRenderer() {
|
|
||||||
return htmlRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
@ -106,8 +90,6 @@ public class MarkwonConfiguration {
|
|||||||
private LinkSpan.Resolver linkResolver;
|
private LinkSpan.Resolver linkResolver;
|
||||||
private UrlProcessor urlProcessor;
|
private UrlProcessor urlProcessor;
|
||||||
private ImageSizeResolver imageSizeResolver;
|
private ImageSizeResolver imageSizeResolver;
|
||||||
private MarkwonHtmlParser htmlParser;
|
|
||||||
private MarkwonHtmlRenderer htmlRenderer;
|
|
||||||
private MarkwonSpansFactory spansFactory;
|
private MarkwonSpansFactory spansFactory;
|
||||||
|
|
||||||
Builder() {
|
Builder() {
|
||||||
@ -122,15 +104,6 @@ public class MarkwonConfiguration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 4.0.0-SNAPSHOT
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public Builder htmlRenderer(@NonNull MarkwonHtmlRenderer htmlRenderer) {
|
|
||||||
this.htmlRenderer = htmlRenderer;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder syntaxHighlight(@NonNull SyntaxHighlight syntaxHighlight) {
|
public Builder syntaxHighlight(@NonNull SyntaxHighlight syntaxHighlight) {
|
||||||
this.syntaxHighlight = syntaxHighlight;
|
this.syntaxHighlight = syntaxHighlight;
|
||||||
@ -149,12 +122,6 @@ public class MarkwonConfiguration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Builder htmlParser(@NonNull MarkwonHtmlParser htmlParser) {
|
|
||||||
this.htmlParser = htmlParser;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 1.0.1
|
* @since 1.0.1
|
||||||
*/
|
*/
|
||||||
@ -177,11 +144,6 @@ public class MarkwonConfiguration {
|
|||||||
asyncDrawableLoader = AsyncDrawableLoader.noOp();
|
asyncDrawableLoader = AsyncDrawableLoader.noOp();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @since 4.0.0-SNAPSHOT
|
|
||||||
if (htmlRenderer == null) {
|
|
||||||
htmlRenderer = MarkwonHtmlRenderer.noOp();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syntaxHighlight == null) {
|
if (syntaxHighlight == null) {
|
||||||
syntaxHighlight = new SyntaxHighlightNoOp();
|
syntaxHighlight = new SyntaxHighlightNoOp();
|
||||||
}
|
}
|
||||||
@ -198,10 +160,6 @@ public class MarkwonConfiguration {
|
|||||||
imageSizeResolver = new ImageSizeResolverDef();
|
imageSizeResolver = new ImageSizeResolverDef();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (htmlParser == null) {
|
|
||||||
htmlParser = MarkwonHtmlParser.noOp();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MarkwonConfiguration(this);
|
return new MarkwonConfiguration(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
118
markwon-core/src/main/java/io/noties/markwon/RegistryImpl.java
Normal file
118
markwon-core/src/main/java/io/noties/markwon/RegistryImpl.java
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package io.noties.markwon;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import io.noties.markwon.core.CorePlugin;
|
||||||
|
|
||||||
|
// @since 4.0.0-SNAPSHOT
|
||||||
|
class RegistryImpl implements MarkwonPlugin.Registry {
|
||||||
|
|
||||||
|
// todo: core-plugin must be (better be) first any way
|
||||||
|
|
||||||
|
private final List<MarkwonPlugin> origin;
|
||||||
|
private final List<MarkwonPlugin> plugins;
|
||||||
|
private final Set<MarkwonPlugin> pending;
|
||||||
|
|
||||||
|
RegistryImpl(@NonNull List<MarkwonPlugin> origin) {
|
||||||
|
this.origin = origin;
|
||||||
|
this.plugins = new ArrayList<>(origin.size());
|
||||||
|
this.pending = new HashSet<>(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public <P extends MarkwonPlugin> P require(@NonNull Class<P> plugin) {
|
||||||
|
return get(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <P extends MarkwonPlugin> void require(
|
||||||
|
@NonNull Class<P> plugin,
|
||||||
|
@NonNull MarkwonPlugin.Action<? super P> action) {
|
||||||
|
action.apply(get(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
List<MarkwonPlugin> process() {
|
||||||
|
for (MarkwonPlugin plugin : origin) {
|
||||||
|
configure(plugin);
|
||||||
|
}
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configure(@NonNull MarkwonPlugin plugin) {
|
||||||
|
|
||||||
|
// important -> check if it's in plugins
|
||||||
|
// if it is -> no need to configure (already configured)
|
||||||
|
|
||||||
|
if (!plugins.contains(plugin)) {
|
||||||
|
|
||||||
|
if (pending.contains(plugin)) {
|
||||||
|
throw new IllegalStateException("Cyclic dependency chain found: " + pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start tracking plugins that are pending for configuration
|
||||||
|
pending.add(plugin);
|
||||||
|
|
||||||
|
plugin.configure(this);
|
||||||
|
|
||||||
|
// stop pending tracking
|
||||||
|
pending.remove(plugin);
|
||||||
|
|
||||||
|
// check again if it's included (a child might've configured it already)
|
||||||
|
// add to out-collection if not already present
|
||||||
|
// this is a bit different from `find` method as it does check for exact instance
|
||||||
|
// and not a sub-type
|
||||||
|
if (!plugins.contains(plugin)) {
|
||||||
|
// core-plugin must always be the first one (if it's present)
|
||||||
|
if (CorePlugin.class.isAssignableFrom(plugin.getClass())) {
|
||||||
|
plugins.add(0, plugin);
|
||||||
|
} else {
|
||||||
|
plugins.add(plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private <P extends MarkwonPlugin> P get(@NonNull Class<P> type) {
|
||||||
|
|
||||||
|
// check if present already in plugins
|
||||||
|
// find in origin, if not found -> throw, else add to out-plugins
|
||||||
|
|
||||||
|
P plugin = find(plugins, type);
|
||||||
|
|
||||||
|
if (plugin == null) {
|
||||||
|
|
||||||
|
plugin = find(origin, type);
|
||||||
|
|
||||||
|
if (plugin == null) {
|
||||||
|
throw new IllegalStateException("Requested plugin is not added: " +
|
||||||
|
"" + type.getName() + ", plugins: " + origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
configure(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static <P extends MarkwonPlugin> P find(
|
||||||
|
@NonNull List<MarkwonPlugin> plugins,
|
||||||
|
@NonNull Class<P> type) {
|
||||||
|
for (MarkwonPlugin plugin : plugins) {
|
||||||
|
if (type.isAssignableFrom(plugin.getClass())) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (P) plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +0,0 @@
|
|||||||
package io.noties.markwon.html;
|
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
class MarkwonHtmlParserNoOp extends MarkwonHtmlParser {
|
|
||||||
@Override
|
|
||||||
public <T extends Appendable & CharSequence> void processFragment(@NonNull T output, @NonNull String htmlFragment) {
|
|
||||||
// no op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flushInlineTags(int documentLength, @NonNull FlushAction<HtmlTag.Inline> action) {
|
|
||||||
action.apply(Collections.<HtmlTag.Inline>emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flushBlockTags(int documentLength, @NonNull FlushAction<HtmlTag.Block> action) {
|
|
||||||
action.apply(Collections.<HtmlTag.Block>emptyList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
// no op
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,15 @@
|
|||||||
|
package io.noties.markwon;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
public abstract class MarkwonAssert {
|
||||||
|
|
||||||
|
public static void assertMessageContains(@NonNull Throwable t, @NonNull String contains) {
|
||||||
|
Assert.assertTrue(t.getMessage(), t.getMessage().contains(contains));
|
||||||
|
}
|
||||||
|
|
||||||
|
private MarkwonAssert() {
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,6 @@ import org.robolectric.RuntimeEnvironment;
|
|||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
import io.noties.markwon.core.MarkwonTheme;
|
import io.noties.markwon.core.MarkwonTheme;
|
||||||
import io.noties.markwon.html.MarkwonHtmlRenderer;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
@ -27,39 +26,6 @@ import static org.mockito.Mockito.verify;
|
|||||||
@Config(manifest = Config.NONE)
|
@Config(manifest = Config.NONE)
|
||||||
public class MarkwonBuilderImplTest {
|
public class MarkwonBuilderImplTest {
|
||||||
|
|
||||||
@Test
|
|
||||||
public void prepare_plugins() {
|
|
||||||
// validate that prepare plugins is calling `ensureImplicitCoreIfHasDependents` and
|
|
||||||
// priority processor
|
|
||||||
|
|
||||||
// final PriorityProcessor priorityProcessor = mock(PriorityProcessor.class);
|
|
||||||
// when(priorityProcessor.process(ArgumentMatchers.<MarkwonPlugin>anyList()))
|
|
||||||
// .thenAnswer(new Answer<Object>() {
|
|
||||||
// @Override
|
|
||||||
// public Object answer(InvocationOnMock invocation) {
|
|
||||||
// return invocation.getArgument(0);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// final MarkwonPlugin plugin = new AbstractMarkwonPlugin() {
|
|
||||||
// @NonNull
|
|
||||||
// @Override
|
|
||||||
// public Priority priority() {
|
|
||||||
// return Priority.after(CorePlugin.class);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// final List<MarkwonPlugin> plugins = preparePlugins(priorityProcessor, Collections.singletonList(plugin));
|
|
||||||
// assertThat(plugins, hasSize(2));
|
|
||||||
// assertThat(plugins, hasItem(plugin));
|
|
||||||
// assertThat(plugins, hasItem(isA(CorePlugin.class)));
|
|
||||||
//
|
|
||||||
// verify(priorityProcessor, times(1))
|
|
||||||
// .process(ArgumentMatchers.<MarkwonPlugin>anyList());
|
|
||||||
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void no_plugins_added_throws() {
|
public void no_plugins_added_throws() {
|
||||||
// there is no sense in having an instance with no plugins registered
|
// there is no sense in having an instance with no plugins registered
|
||||||
|
@ -0,0 +1,194 @@
|
|||||||
|
package io.noties.markwon;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.noties.markwon.core.CorePlugin;
|
||||||
|
|
||||||
|
import static io.noties.markwon.MarkwonAssert.assertMessageContains;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(manifest = Config.NONE)
|
||||||
|
public class RegistryImplTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void single_plugin_requires_self() {
|
||||||
|
// detect recursive require
|
||||||
|
|
||||||
|
final class Plugin extends AbstractMarkwonPlugin {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
registry.require(Plugin.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final MarkwonPlugin plugin = new Plugin();
|
||||||
|
|
||||||
|
final RegistryImpl impl = new RegistryImpl(Collections.singletonList(plugin));
|
||||||
|
|
||||||
|
try {
|
||||||
|
impl.process();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
assertMessageContains(t, "Cyclic dependency chain found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void plugins_dependency_cycle() {
|
||||||
|
|
||||||
|
final Map<String, Class<? extends MarkwonPlugin>> map = new HashMap<>();
|
||||||
|
|
||||||
|
final class A extends AbstractMarkwonPlugin {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
registry.require(map.get("A"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class B extends AbstractMarkwonPlugin {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
registry.require(map.get("B"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class C extends AbstractMarkwonPlugin {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
registry.require(map.get("C"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
map.put("A", B.class);
|
||||||
|
map.put("B", C.class);
|
||||||
|
map.put("C", A.class);
|
||||||
|
|
||||||
|
final RegistryImpl impl =
|
||||||
|
new RegistryImpl(Arrays.asList((MarkwonPlugin) new A(), new B(), new C()));
|
||||||
|
|
||||||
|
try {
|
||||||
|
impl.process();
|
||||||
|
fail();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
assertMessageContains(t, "Cyclic dependency chain found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void plugins_no_dependency_cycle() {
|
||||||
|
|
||||||
|
final class C extends AbstractMarkwonPlugin {
|
||||||
|
}
|
||||||
|
|
||||||
|
final class B extends AbstractMarkwonPlugin {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
registry.require(C.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class A extends AbstractMarkwonPlugin {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
registry.require(B.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final RegistryImpl impl =
|
||||||
|
new RegistryImpl(Arrays.asList((MarkwonPlugin) new A(), new B(), new C()));
|
||||||
|
|
||||||
|
impl.process();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dependency_not_satisfied() {
|
||||||
|
// when require is called for plugin not added
|
||||||
|
|
||||||
|
final class A extends AbstractMarkwonPlugin {
|
||||||
|
}
|
||||||
|
|
||||||
|
final class B extends AbstractMarkwonPlugin {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
registry.require(A.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final RegistryImpl impl =
|
||||||
|
new RegistryImpl(Collections.singletonList((MarkwonPlugin) new B()));
|
||||||
|
|
||||||
|
try {
|
||||||
|
impl.process();
|
||||||
|
fail();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
assertMessageContains(t, "Requested plugin is not added");
|
||||||
|
assertMessageContains(t, A.class.getName()); // ? if it's null for local class?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void core_plugin_first() {
|
||||||
|
// if core-plugin is present, hen it should be the first one
|
||||||
|
|
||||||
|
final CorePlugin plugin = CorePlugin.create();
|
||||||
|
|
||||||
|
final RegistryImpl impl = new RegistryImpl(Arrays.asList(
|
||||||
|
mock(MarkwonPlugin.class),
|
||||||
|
mock(MarkwonPlugin.class),
|
||||||
|
plugin
|
||||||
|
));
|
||||||
|
|
||||||
|
final List<MarkwonPlugin> plugins = impl.process();
|
||||||
|
assertEquals(3, plugins.size());
|
||||||
|
assertEquals(plugin, plugins.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void correct_order() {
|
||||||
|
|
||||||
|
final class A extends AbstractMarkwonPlugin {
|
||||||
|
}
|
||||||
|
|
||||||
|
final class B extends AbstractMarkwonPlugin {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
registry.require(A.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class C extends AbstractMarkwonPlugin {
|
||||||
|
@Override
|
||||||
|
public void configure(@NonNull Registry registry) {
|
||||||
|
registry.require(B.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final A a = new A();
|
||||||
|
final B b = new B();
|
||||||
|
final C c = new C();
|
||||||
|
|
||||||
|
final RegistryImpl impl = new RegistryImpl(Arrays.asList(
|
||||||
|
(MarkwonPlugin) c, b, a));
|
||||||
|
|
||||||
|
final List<MarkwonPlugin> plugins = impl.process();
|
||||||
|
assertEquals(3, plugins.size());
|
||||||
|
assertEquals(a, plugins.get(0));
|
||||||
|
assertEquals(b, plugins.get(1));
|
||||||
|
assertEquals(c, plugins.get(2));
|
||||||
|
}
|
||||||
|
}
|
@ -7,13 +7,13 @@ import org.commonmark.node.HtmlBlock;
|
|||||||
import org.commonmark.node.HtmlInline;
|
import org.commonmark.node.HtmlInline;
|
||||||
import org.commonmark.node.Node;
|
import org.commonmark.node.Node;
|
||||||
|
|
||||||
import io.noties.markwon.html.tag.ImageHandler;
|
|
||||||
import io.noties.markwon.AbstractMarkwonPlugin;
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||||
import io.noties.markwon.MarkwonConfiguration;
|
import io.noties.markwon.MarkwonConfiguration;
|
||||||
import io.noties.markwon.MarkwonVisitor;
|
import io.noties.markwon.MarkwonVisitor;
|
||||||
import io.noties.markwon.html.tag.BlockquoteHandler;
|
import io.noties.markwon.html.tag.BlockquoteHandler;
|
||||||
import io.noties.markwon.html.tag.EmphasisHandler;
|
import io.noties.markwon.html.tag.EmphasisHandler;
|
||||||
import io.noties.markwon.html.tag.HeadingHandler;
|
import io.noties.markwon.html.tag.HeadingHandler;
|
||||||
|
import io.noties.markwon.html.tag.ImageHandler;
|
||||||
import io.noties.markwon.html.tag.LinkHandler;
|
import io.noties.markwon.html.tag.LinkHandler;
|
||||||
import io.noties.markwon.html.tag.ListHandler;
|
import io.noties.markwon.html.tag.ListHandler;
|
||||||
import io.noties.markwon.html.tag.StrikeHandler;
|
import io.noties.markwon.html.tag.StrikeHandler;
|
||||||
@ -53,10 +53,13 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
public static final float SCRIPT_DEF_TEXT_SIZE_RATIO = .75F;
|
public static final float SCRIPT_DEF_TEXT_SIZE_RATIO = .75F;
|
||||||
|
|
||||||
private final MarkwonHtmlRendererImpl.Builder builder;
|
private final MarkwonHtmlRendererImpl.Builder builder;
|
||||||
|
private final MarkwonHtmlParser htmlParser;
|
||||||
|
private MarkwonHtmlRenderer htmlRenderer;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
HtmlPlugin() {
|
HtmlPlugin() {
|
||||||
this.builder = new MarkwonHtmlRendererImpl.Builder();
|
this.builder = new MarkwonHtmlRendererImpl.Builder();
|
||||||
|
this.htmlParser = MarkwonHtmlParserImpl.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,6 +107,8 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder configurationBuilder) {
|
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder configurationBuilder) {
|
||||||
|
|
||||||
|
// @since 4.0.0-SNAPSHOT we init internal html-renderer here (marks the end of configuration)
|
||||||
|
|
||||||
final MarkwonHtmlRendererImpl.Builder builder = this.builder;
|
final MarkwonHtmlRendererImpl.Builder builder = this.builder;
|
||||||
|
|
||||||
if (!builder.excludeDefaults()) {
|
if (!builder.excludeDefaults()) {
|
||||||
@ -123,15 +128,17 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
builder.addDefaultTagHandler(new HeadingHandler());
|
builder.addDefaultTagHandler(new HeadingHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
configurationBuilder
|
htmlRenderer = builder.build();
|
||||||
.htmlRenderer(builder.build())
|
|
||||||
.htmlParser(MarkwonHtmlParserImpl.create());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterRender(@NonNull Node node, @NonNull MarkwonVisitor visitor) {
|
public void afterRender(@NonNull Node node, @NonNull MarkwonVisitor visitor) {
|
||||||
final MarkwonConfiguration configuration = visitor.configuration();
|
final MarkwonHtmlRenderer htmlRenderer = this.htmlRenderer;
|
||||||
configuration.htmlRenderer().render(visitor, configuration.htmlParser());
|
if (htmlRenderer != null) {
|
||||||
|
htmlRenderer.render(visitor, htmlParser);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unexpected state, html-renderer is not defined");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -153,7 +160,7 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
|
|||||||
|
|
||||||
private void visitHtml(@NonNull MarkwonVisitor visitor, @Nullable String html) {
|
private void visitHtml(@NonNull MarkwonVisitor visitor, @Nullable String html) {
|
||||||
if (html != null) {
|
if (html != null) {
|
||||||
visitor.configuration().htmlParser().processFragment(visitor.builder(), html);
|
htmlParser.processFragment(visitor.builder(), html);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,6 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public abstract class MarkwonHtmlParser {
|
public abstract class MarkwonHtmlParser {
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method to create a `no-op` implementation (no parsing)
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public static MarkwonHtmlParser noOp() {
|
|
||||||
return new MarkwonHtmlParserNoOp();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface FlushAction<T> {
|
public interface FlushAction<T> {
|
||||||
void apply(@NonNull List<T> tags);
|
void apply(@NonNull List<T> tags);
|
||||||
}
|
}
|
@ -10,14 +10,6 @@ import io.noties.markwon.MarkwonVisitor;
|
|||||||
*/
|
*/
|
||||||
public abstract class MarkwonHtmlRenderer {
|
public abstract class MarkwonHtmlRenderer {
|
||||||
|
|
||||||
/**
|
|
||||||
* @since 4.0.0-SNAPSHOT
|
|
||||||
*/
|
|
||||||
@NonNull
|
|
||||||
public static MarkwonHtmlRenderer noOp() {
|
|
||||||
return new MarkwonHtmlRendererNoOp();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void render(
|
public abstract void render(
|
||||||
@NonNull MarkwonVisitor visitor,
|
@NonNull MarkwonVisitor visitor,
|
||||||
@NonNull MarkwonHtmlParser parser
|
@NonNull MarkwonHtmlParser parser
|
@ -3,6 +3,7 @@ package io.noties.markwon.image;
|
|||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.annotation.VisibleForTesting;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@ -10,16 +11,16 @@ import org.commonmark.node.Image;
|
|||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||||
|
import io.noties.markwon.MarkwonConfiguration;
|
||||||
import io.noties.markwon.MarkwonPlugin;
|
import io.noties.markwon.MarkwonPlugin;
|
||||||
|
import io.noties.markwon.MarkwonSpansFactory;
|
||||||
import io.noties.markwon.image.data.DataUriSchemeHandler;
|
import io.noties.markwon.image.data.DataUriSchemeHandler;
|
||||||
import io.noties.markwon.image.file.FileSchemeHandler;
|
import io.noties.markwon.image.file.FileSchemeHandler;
|
||||||
import io.noties.markwon.image.gif.GifMediaDecoder;
|
import io.noties.markwon.image.gif.GifMediaDecoder;
|
||||||
import io.noties.markwon.image.network.NetworkSchemeHandler;
|
import io.noties.markwon.image.network.NetworkSchemeHandler;
|
||||||
import io.noties.markwon.image.network.OkHttpNetworkSchemeHandler;
|
import io.noties.markwon.image.network.OkHttpNetworkSchemeHandler;
|
||||||
import io.noties.markwon.image.svg.SvgMediaDecoder;
|
import io.noties.markwon.image.svg.SvgMediaDecoder;
|
||||||
import io.noties.markwon.AbstractMarkwonPlugin;
|
|
||||||
import io.noties.markwon.MarkwonConfiguration;
|
|
||||||
import io.noties.markwon.MarkwonSpansFactory;
|
|
||||||
|
|
||||||
@SuppressWarnings({"UnusedReturnValue", "WeakerAccess"})
|
@SuppressWarnings({"UnusedReturnValue", "WeakerAccess"})
|
||||||
public class ImagesPlugin extends AbstractMarkwonPlugin {
|
public class ImagesPlugin extends AbstractMarkwonPlugin {
|
||||||
@ -70,7 +71,18 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
|
|||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final AsyncDrawableLoaderBuilder builder = new AsyncDrawableLoaderBuilder();
|
private final AsyncDrawableLoaderBuilder builder;
|
||||||
|
|
||||||
|
// @since 4.0.0-SNAPSHOT
|
||||||
|
ImagesPlugin() {
|
||||||
|
this(new AsyncDrawableLoaderBuilder());
|
||||||
|
}
|
||||||
|
|
||||||
|
// @since 4.0.0-SNAPSHOT
|
||||||
|
@VisibleForTesting
|
||||||
|
ImagesPlugin(@NonNull AsyncDrawableLoaderBuilder builder) {
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional (by default new cached thread executor will be used)
|
* Optional (by default new cached thread executor will be used)
|
||||||
|
@ -18,6 +18,7 @@ import static org.junit.Assert.assertFalse;
|
|||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@ -203,4 +204,16 @@ public class AsyncDrawableLoaderBuilderTest {
|
|||||||
builder.removeMediaDecoder(media);
|
builder.removeMediaDecoder(media);
|
||||||
assertNull(builder.mediaDecoders.get(media));
|
assertNull(builder.mediaDecoders.get(media));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void cannot_build_twice() {
|
||||||
|
|
||||||
|
builder.build();
|
||||||
|
try {
|
||||||
|
builder.build();
|
||||||
|
fail();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
assertTrue(t.getMessage(), t.getMessage().contains("has already been configured"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -27,6 +27,7 @@ import static org.mockito.ArgumentMatchers.eq;
|
|||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@ -175,4 +176,70 @@ public class ImagesPluginTest {
|
|||||||
verify(textView, times(1))
|
verify(textView, times(1))
|
||||||
.getTag(eq(R.id.markwon_drawables_scheduler_last_text_hashcode));
|
.getTag(eq(R.id.markwon_drawables_scheduler_last_text_hashcode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void methods_redirected_to_builder() {
|
||||||
|
|
||||||
|
final AsyncDrawableLoaderBuilder builder = mock(AsyncDrawableLoaderBuilder.class);
|
||||||
|
final ImagesPlugin plugin = new ImagesPlugin(builder);
|
||||||
|
|
||||||
|
// executor service
|
||||||
|
{
|
||||||
|
final ExecutorService executorService = mock(ExecutorService.class);
|
||||||
|
plugin.executorService(executorService);
|
||||||
|
verify(builder, times(1)).executorService(eq(executorService));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add scheme-handler
|
||||||
|
{
|
||||||
|
final SchemeHandler schemeHandler = mock(SchemeHandler.class);
|
||||||
|
plugin.addSchemeHandler(schemeHandler);
|
||||||
|
verify(builder, times(1)).addSchemeHandler(eq(schemeHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
// add media-decoder
|
||||||
|
{
|
||||||
|
final MediaDecoder mediaDecoder = mock(MediaDecoder.class);
|
||||||
|
plugin.addMediaDecoder(mediaDecoder);
|
||||||
|
verify(builder, times(1)).addMediaDecoder(eq(mediaDecoder));
|
||||||
|
}
|
||||||
|
|
||||||
|
// default-media-decoder
|
||||||
|
{
|
||||||
|
final MediaDecoder mediaDecoder = mock(MediaDecoder.class);
|
||||||
|
plugin.defaultMediaDecoder(mediaDecoder);
|
||||||
|
verify(builder, times(1)).defaultMediaDecoder(eq(mediaDecoder));
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove scheme-handler
|
||||||
|
{
|
||||||
|
final String scheme = "yo";
|
||||||
|
plugin.removeSchemeHandler(scheme);
|
||||||
|
verify(builder, times(1)).removeSchemeHandler(eq(scheme));
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove media-decoder
|
||||||
|
{
|
||||||
|
final String contentType = "fa/ke";
|
||||||
|
plugin.removeMediaDecoder(contentType);
|
||||||
|
verify(builder, times(1)).removeMediaDecoder(eq(contentType));
|
||||||
|
}
|
||||||
|
|
||||||
|
// placeholder provider
|
||||||
|
{
|
||||||
|
final ImagesPlugin.PlaceholderProvider placeholderProvider =
|
||||||
|
mock(ImagesPlugin.PlaceholderProvider.class);
|
||||||
|
plugin.placeholderProvider(placeholderProvider);
|
||||||
|
verify(builder, times(1)).placeholderProvider(eq(placeholderProvider));
|
||||||
|
}
|
||||||
|
|
||||||
|
// error-handler
|
||||||
|
{
|
||||||
|
final ImagesPlugin.ErrorHandler errorHandler = mock(ImagesPlugin.ErrorHandler.class);
|
||||||
|
plugin.errorHandler(errorHandler);
|
||||||
|
verify(builder, times(1)).errorHandler(eq(errorHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyNoMoreInteractions(builder);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user