Unified html and image modules

This commit is contained in:
Dimitry Ivanov 2019-06-04 17:18:42 +03:00
parent dba07e3f3c
commit 4b918bf094
6 changed files with 58 additions and 52 deletions

View File

@ -6,7 +6,7 @@ org.gradle.configureondemand=true
android.enableBuildCache=true android.enableBuildCache=true
android.buildCacheDir=build/pre-dex-cache android.buildCacheDir=build/pre-dex-cache
VERSION_NAME=3.1.0-SNAPSHOT VERSION_NAME=4.0.0-SNAPSHOT
GROUP=ru.noties.markwon GROUP=ru.noties.markwon
POM_DESCRIPTION=Markwon markdown for Android POM_DESCRIPTION=Markwon markdown for Android

View File

@ -10,6 +10,17 @@ import org.commonmark.node.Node;
import ru.noties.markwon.AbstractMarkwonPlugin; import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.MarkwonConfiguration; import ru.noties.markwon.MarkwonConfiguration;
import ru.noties.markwon.MarkwonVisitor; import ru.noties.markwon.MarkwonVisitor;
import ru.noties.markwon.html.tag.BlockquoteHandler;
import ru.noties.markwon.html.tag.EmphasisHandler;
import ru.noties.markwon.html.tag.HeadingHandler;
import ru.noties.markwon.html.tag.ImageHandler;
import ru.noties.markwon.html.tag.LinkHandler;
import ru.noties.markwon.html.tag.ListHandler;
import ru.noties.markwon.html.tag.StrikeHandler;
import ru.noties.markwon.html.tag.StrongEmphasisHandler;
import ru.noties.markwon.html.tag.SubScriptHandler;
import ru.noties.markwon.html.tag.SuperScriptHandler;
import ru.noties.markwon.html.tag.UnderlineHandler;
/** /**
* @since 3.0.0 * @since 3.0.0
@ -73,9 +84,29 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
} }
@Override @Override
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { public void configureConfiguration(@NonNull MarkwonConfiguration.Builder configurationBuilder) {
builder
.htmlRenderer(this.builder.build()) final MarkwonHtmlRendererImpl.Builder builder = this.builder;
if (!builder.excludeDefaults()) {
// please note that it's better to not checkState for
// this method call (minor optimization), final `build` method call
// will check for the state and throw an exception if applicable
builder.addDefaultTagHandler(ImageHandler.create());
builder.addDefaultTagHandler(new LinkHandler());
builder.addDefaultTagHandler(new BlockquoteHandler());
builder.addDefaultTagHandler(new SubScriptHandler());
builder.addDefaultTagHandler(new SuperScriptHandler());
builder.addDefaultTagHandler(new StrongEmphasisHandler());
builder.addDefaultTagHandler(new StrikeHandler());
builder.addDefaultTagHandler(new UnderlineHandler());
builder.addDefaultTagHandler(new ListHandler());
builder.addDefaultTagHandler(new EmphasisHandler());
builder.addDefaultTagHandler(new HeadingHandler());
}
configurationBuilder
.htmlRenderer(builder.build())
.htmlParser(MarkwonHtmlParserImpl.create()); .htmlParser(MarkwonHtmlParserImpl.create());
} }

View File

@ -9,17 +9,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import ru.noties.markwon.MarkwonVisitor; import ru.noties.markwon.MarkwonVisitor;
import ru.noties.markwon.html.tag.BlockquoteHandler;
import ru.noties.markwon.html.tag.EmphasisHandler;
import ru.noties.markwon.html.tag.HeadingHandler;
import ru.noties.markwon.html.tag.ImageHandler;
import ru.noties.markwon.html.tag.LinkHandler;
import ru.noties.markwon.html.tag.ListHandler;
import ru.noties.markwon.html.tag.StrikeHandler;
import ru.noties.markwon.html.tag.StrongEmphasisHandler;
import ru.noties.markwon.html.tag.SubScriptHandler;
import ru.noties.markwon.html.tag.SuperScriptHandler;
import ru.noties.markwon.html.tag.UnderlineHandler;
class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer { class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer {
@ -128,6 +117,10 @@ class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer {
this.excludeDefaults = excludeDefaults; this.excludeDefaults = excludeDefaults;
} }
boolean excludeDefaults() {
return excludeDefaults;
}
@NonNull @NonNull
public MarkwonHtmlRenderer build() { public MarkwonHtmlRenderer build() {
@ -135,11 +128,6 @@ class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer {
isBuilt = true; isBuilt = true;
if (!excludeDefaults) {
// register default handlers, check if a handler is present already for specified tag
registerDefaultHandlers();
}
// okay, let's validate that we have at least one tagHandler registered // okay, let's validate that we have at least one tagHandler registered
// if we have none -> return no-op implementation // if we have none -> return no-op implementation
return tagHandlers.size() > 0 return tagHandlers.size() > 0
@ -153,21 +141,7 @@ class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer {
} }
} }
private void registerDefaultHandlers() { void addDefaultTagHandler(@NonNull TagHandler tagHandler) {
add(ImageHandler.create());
add(new LinkHandler());
add(new BlockquoteHandler());
add(new SubScriptHandler());
add(new SuperScriptHandler());
add(new StrongEmphasisHandler());
add(new StrikeHandler());
add(new UnderlineHandler());
add(new ListHandler());
add(new EmphasisHandler());
add(new HeadingHandler());
}
private void add(@NonNull TagHandler tagHandler) {
for (String tag : tagHandler.supportedTags()) { for (String tag : tagHandler.supportedTags()) {
if (!tagHandlers.containsKey(tag)) { if (!tagHandlers.containsKey(tag)) {
tagHandlers.put(tag, tagHandler); tagHandlers.put(tag, tagHandler);

View File

@ -34,30 +34,36 @@ class AsyncDrawableLoaderBuilder {
} }
void executorService(@NonNull ExecutorService executorService) { void executorService(@NonNull ExecutorService executorService) {
checkState();
this.executorService = executorService; this.executorService = executorService;
} }
void addSchemeHandler(@NonNull SchemeHandler schemeHandler) { void addSchemeHandler(@NonNull SchemeHandler schemeHandler) {
checkState();
for (String scheme : schemeHandler.supportedSchemes()) { for (String scheme : schemeHandler.supportedSchemes()) {
schemeHandlers.put(scheme, schemeHandler); schemeHandlers.put(scheme, schemeHandler);
} }
} }
void addMediaDecoder(@NonNull MediaDecoder mediaDecoder) { void addMediaDecoder(@NonNull MediaDecoder mediaDecoder) {
checkState();
for (String type : mediaDecoder.supportedTypes()) { for (String type : mediaDecoder.supportedTypes()) {
mediaDecoders.put(type, mediaDecoder); mediaDecoders.put(type, mediaDecoder);
} }
} }
void defaultMediaDecoder(@Nullable MediaDecoder mediaDecoder) { void defaultMediaDecoder(@Nullable MediaDecoder mediaDecoder) {
checkState();
this.defaultMediaDecoder = mediaDecoder; this.defaultMediaDecoder = mediaDecoder;
} }
void removeSchemeHandler(@NonNull String scheme) { void removeSchemeHandler(@NonNull String scheme) {
checkState();
schemeHandlers.remove(scheme); schemeHandlers.remove(scheme);
} }
void removeMediaDecoder(@NonNull String contentType) { void removeMediaDecoder(@NonNull String contentType) {
checkState();
mediaDecoders.remove(contentType); mediaDecoders.remove(contentType);
} }
@ -65,6 +71,7 @@ class AsyncDrawableLoaderBuilder {
* @since 3.0.0 * @since 3.0.0
*/ */
void placeholderProvider(@NonNull ImagesPlugin.PlaceholderProvider placeholderDrawableProvider) { void placeholderProvider(@NonNull ImagesPlugin.PlaceholderProvider placeholderDrawableProvider) {
checkState();
this.placeholderProvider = placeholderDrawableProvider; this.placeholderProvider = placeholderDrawableProvider;
} }
@ -72,12 +79,15 @@ class AsyncDrawableLoaderBuilder {
* @since 3.0.0 * @since 3.0.0
*/ */
void errorHandler(@NonNull ImagesPlugin.ErrorHandler errorHandler) { void errorHandler(@NonNull ImagesPlugin.ErrorHandler errorHandler) {
checkState();
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
} }
@NonNull @NonNull
AsyncDrawableLoader build() { AsyncDrawableLoader build() {
checkState();
isBuilt = true; isBuilt = true;
if (executorService == null) { if (executorService == null) {
@ -86,4 +96,11 @@ class AsyncDrawableLoaderBuilder {
return new AsyncDrawableLoaderImpl(this); return new AsyncDrawableLoaderImpl(this);
} }
private void checkState() {
if (isBuilt) {
throw new IllegalStateException("ImagesPlugin has already been configured " +
"and cannot be modified any further");
}
}
} }

View File

@ -72,7 +72,6 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
*/ */
@NonNull @NonNull
public ImagesPlugin executorService(@NonNull ExecutorService executorService) { public ImagesPlugin executorService(@NonNull ExecutorService executorService) {
checkBuilderState();
builder.executorService(executorService); builder.executorService(executorService);
return this; return this;
} }
@ -87,7 +86,6 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
*/ */
@NonNull @NonNull
public ImagesPlugin addSchemeHandler(@NonNull SchemeHandler schemeHandler) { public ImagesPlugin addSchemeHandler(@NonNull SchemeHandler schemeHandler) {
checkBuilderState();
builder.addSchemeHandler(schemeHandler); builder.addSchemeHandler(schemeHandler);
return this; return this;
} }
@ -100,7 +98,6 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
*/ */
@NonNull @NonNull
public ImagesPlugin addMediaDecoder(@NonNull MediaDecoder mediaDecoder) { public ImagesPlugin addMediaDecoder(@NonNull MediaDecoder mediaDecoder) {
checkBuilderState();
builder.addMediaDecoder(mediaDecoder); builder.addMediaDecoder(mediaDecoder);
return this; return this;
} }
@ -114,7 +111,6 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
*/ */
@NonNull @NonNull
public ImagesPlugin defaultMediaDecoder(@Nullable MediaDecoder mediaDecoder) { public ImagesPlugin defaultMediaDecoder(@Nullable MediaDecoder mediaDecoder) {
checkBuilderState();
builder.defaultMediaDecoder(mediaDecoder); builder.defaultMediaDecoder(mediaDecoder);
return this; return this;
} }
@ -124,7 +120,6 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
*/ */
@NonNull @NonNull
public ImagesPlugin removeSchemeHandler(@NonNull String scheme) { public ImagesPlugin removeSchemeHandler(@NonNull String scheme) {
checkBuilderState();
builder.removeSchemeHandler(scheme); builder.removeSchemeHandler(scheme);
return this; return this;
} }
@ -134,7 +129,6 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
*/ */
@NonNull @NonNull
public ImagesPlugin removeMediaDecoder(@NonNull String contentType) { public ImagesPlugin removeMediaDecoder(@NonNull String contentType) {
checkBuilderState();
builder.removeMediaDecoder(contentType); builder.removeMediaDecoder(contentType);
return this; return this;
} }
@ -144,7 +138,6 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
*/ */
@NonNull @NonNull
public ImagesPlugin placeholderProvider(@NonNull PlaceholderProvider placeholderProvider) { public ImagesPlugin placeholderProvider(@NonNull PlaceholderProvider placeholderProvider) {
checkBuilderState();
builder.placeholderProvider(placeholderProvider); builder.placeholderProvider(placeholderProvider);
return this; return this;
} }
@ -155,14 +148,12 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
*/ */
@NonNull @NonNull
public ImagesPlugin errorHandler(@NonNull ErrorHandler errorHandler) { public ImagesPlugin errorHandler(@NonNull ErrorHandler errorHandler) {
checkBuilderState();
builder.errorHandler(errorHandler); builder.errorHandler(errorHandler);
return this; return this;
} }
@Override @Override
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) {
checkBuilderState();
builder.asyncDrawableLoader(this.builder.build()); builder.asyncDrawableLoader(this.builder.build());
} }
@ -180,11 +171,4 @@ public class ImagesPlugin extends AbstractMarkwonPlugin {
public void afterSetText(@NonNull TextView textView) { public void afterSetText(@NonNull TextView textView) {
AsyncDrawableScheduler.schedule(textView); AsyncDrawableScheduler.schedule(textView);
} }
private void checkBuilderState() {
if (builder.isBuilt) {
throw new IllegalStateException("ImagesPlugin has already been configured " +
"and cannot be modified any further");
}
}
} }

View File

@ -4,6 +4,6 @@ Use this module (or take a hint from it) if you would need _linkify_ capabilitie
use `TextView.setAutolinkMask` (or specify `autolink` in XML) because it will remove all use `TextView.setAutolinkMask` (or specify `autolink` in XML) because it will remove all
existing links and keep only the ones it creates. existing links and keep only the ones it creates.
Please note that usage of this plugin introduces significant performance drop due not Please note that usage of this plugin introduces significant performance drop due to not
optimal implementation of underlying `android.text.util.Linkify`. If you have any ideas of how optimal implementation of underlying `android.text.util.Linkify`. If you have any ideas of how
to improve this - PR are welcome! to improve this - PR are welcome!