Bring back html-api to core module

This commit is contained in:
Dimitry Ivanov 2019-01-04 18:39:26 +03:00
parent ec3d596d8a
commit 6f025b9a95
19 changed files with 344 additions and 257 deletions

View File

@ -8,41 +8,57 @@ import org.commonmark.node.HtmlInline;
import org.commonmark.node.Node;
import ru.noties.markwon.AbstractMarkwonPlugin;
import ru.noties.markwon.MarkwonConfiguration;
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
*/
public class HtmlPlugin extends AbstractMarkwonPlugin {
@NonNull
public static HtmlPlugin create() {
return create(MarkwonHtmlRendererImpl.create(), MarkwonHtmlParserImpl.create());
return new HtmlPlugin();
}
@NonNull
public static HtmlPlugin create(@NonNull MarkwonHtmlRenderer renderer) {
return create(renderer, MarkwonHtmlParserImpl.create());
public static final float SCRIPT_DEF_TEXT_SIZE_RATIO = .75F;
@Override
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) {
builder.htmlParser(MarkwonHtmlParserImpl.create());
}
@NonNull
public static HtmlPlugin create(@NonNull MarkwonHtmlParser parser) {
return create(MarkwonHtmlRendererImpl.create(), parser);
}
@NonNull
public static HtmlPlugin create(@NonNull MarkwonHtmlRenderer renderer, @NonNull MarkwonHtmlParser parser) {
return new HtmlPlugin(renderer, parser);
}
private final MarkwonHtmlRenderer renderer;
private final MarkwonHtmlParser parser;
public HtmlPlugin(@NonNull MarkwonHtmlRenderer renderer, @NonNull MarkwonHtmlParser parser) {
this.renderer = renderer;
this.parser = parser;
@Override
public void configureHtmlRenderer(@NonNull MarkwonHtmlRenderer.Builder builder) {
builder
.addHandler(new EmphasisHandler(), "i", "em", "cite", "dfn")
.addHandler(new StrongEmphasisHandler(), "b", "strong")
.addHandler(new SuperScriptHandler(), "sup")
.addHandler(new SubScriptHandler(), "sub")
.addHandler(new UnderlineHandler(), "u", "ins")
.addHandler(new StrikeHandler(), "s", "del")
.addHandler(new LinkHandler(), "a")
.addHandler(new ListHandler(), "ul", "ol")
.addHandler(ImageHandler.create(), "img")
.addHandler(new BlockquoteHandler(), "blockquote")
.addHandler(new HeadingHandler(), "h1", "h2", "h3", "h4", "h5", "h6");
}
@Override
public void afterRender(@NonNull Node node, @NonNull MarkwonVisitor visitor) {
renderer.render(visitor, parser);
final MarkwonConfiguration configuration = visitor.configuration();
configuration.htmlRenderer().render(visitor, configuration.htmlParser());
}
@Override
@ -64,7 +80,7 @@ public class HtmlPlugin extends AbstractMarkwonPlugin {
private void visitHtml(@NonNull MarkwonVisitor visitor, @Nullable String html) {
if (html != null) {
parser.processFragment(visitor.builder(), html);
visitor.configuration().htmlParser().processFragment(visitor.builder(), html);
}
}
}

View File

@ -1,20 +0,0 @@
package ru.noties.markwon.html;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import ru.noties.markwon.MarkwonVisitor;
/**
* @since 2.0.0
*/
public abstract class MarkwonHtmlRenderer {
public abstract void render(
@NonNull MarkwonVisitor visitor,
@NonNull MarkwonHtmlParser parser
);
@Nullable
public abstract TagHandler tagHandler(@NonNull String tagName);
}

View File

@ -1,195 +0,0 @@
package ru.noties.markwon.html;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
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;
public class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer {
@NonNull
public static MarkwonHtmlRendererImpl create() {
return builderWithDefaults().build();
}
/**
* @since 3.0.0
*/
@NonNull
public static MarkwonHtmlRendererImpl create(boolean allowNonClosedTags) {
return builderWithDefaults(allowNonClosedTags).build();
}
@NonNull
public static Builder builderWithDefaults() {
return builderWithDefaults(false);
}
/**
* @since 3.0.0
*/
@NonNull
public static Builder builderWithDefaults(boolean allowNonClosedTags) {
final EmphasisHandler emphasisHandler = new EmphasisHandler();
final StrongEmphasisHandler strongEmphasisHandler = new StrongEmphasisHandler();
final StrikeHandler strikeHandler = new StrikeHandler();
final UnderlineHandler underlineHandler = new UnderlineHandler();
final ListHandler listHandler = new ListHandler();
return builder()
.allowNonClosedTags(allowNonClosedTags)
.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", underlineHandler)
.handler("ins", underlineHandler)
.handler("del", strikeHandler)
.handler("s", strikeHandler)
.handler("strike", strikeHandler)
.handler("a", new LinkHandler())
.handler("ul", listHandler)
.handler("ol", listHandler)
.handler("img", ImageHandler.create())
.handler("blockquote", new BlockquoteHandler())
.handler("h1", new HeadingHandler(1))
.handler("h2", new HeadingHandler(2))
.handler("h3", new HeadingHandler(3))
.handler("h4", new HeadingHandler(4))
.handler("h5", new HeadingHandler(5))
.handler("h6", new HeadingHandler(6));
}
@NonNull
public static Builder builder() {
return new Builder();
}
public static final float SCRIPT_DEF_TEXT_SIZE_RATIO = .75F;
private final boolean allowNonClosedTags;
private final Map<String, TagHandler> tagHandlers;
private MarkwonHtmlRendererImpl(boolean allowNonClosedTags, @NonNull Map<String, TagHandler> tagHandlers) {
this.allowNonClosedTags = allowNonClosedTags;
this.tagHandlers = tagHandlers;
}
@Override
public void render(
@NonNull final MarkwonVisitor visitor,
@NonNull MarkwonHtmlParser parser) {
final int end;
if (!allowNonClosedTags) {
end = HtmlTag.NO_END;
} else {
end = visitor.length();
}
parser.flushInlineTags(end, new MarkwonHtmlParser.FlushAction<HtmlTag.Inline>() {
@Override
public void apply(@NonNull List<HtmlTag.Inline> tags) {
TagHandler handler;
for (HtmlTag.Inline inline : tags) {
// if tag is not closed -> do not render
if (!inline.isClosed()) {
continue;
}
handler = tagHandler(inline.name());
if (handler != null) {
handler.handle(visitor, MarkwonHtmlRendererImpl.this, inline);
}
}
}
});
parser.flushBlockTags(end, new MarkwonHtmlParser.FlushAction<HtmlTag.Block>() {
@Override
public void apply(@NonNull List<HtmlTag.Block> tags) {
TagHandler handler;
for (HtmlTag.Block block : tags) {
if (!block.isClosed()) {
continue;
}
handler = tagHandler(block.name());
if (handler != null) {
handler.handle(visitor, MarkwonHtmlRendererImpl.this, block);
} 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);
}
public static class Builder {
private final Map<String, TagHandler> tagHandlers = new HashMap<>(2);
private boolean allowNonClosedTags;
@NonNull
public Builder handler(@NonNull String tagName, @NonNull TagHandler tagHandler) {
tagHandlers.put(tagName.toLowerCase(Locale.US), tagHandler);
return this;
}
/**
* @param allowNonClosedTags that indicates if non-closed html tags should be rendered.
* If this argument is true then all non-closed HTML tags
* will be closed at the end of a document. Otherwise they will
* be delivered non-closed {@code HtmlTag#isClosed()} and thus not
* rendered at all
* @since 3.0.0
*/
@NonNull
public Builder allowNonClosedTags(boolean allowNonClosedTags) {
this.allowNonClosedTags = allowNonClosedTags;
return this;
}
@NonNull
public MarkwonHtmlRendererImpl build() {
return new MarkwonHtmlRendererImpl(allowNonClosedTags, Collections.unmodifiableMap(tagHandlers));
}
}
}

View File

@ -4,7 +4,7 @@ import android.support.annotation.NonNull;
import android.text.TextPaint;
import android.text.style.MetricAffectingSpan;
import ru.noties.markwon.html.MarkwonHtmlRendererImpl;
import ru.noties.markwon.html.HtmlPlugin;
public class SubScriptSpan extends MetricAffectingSpan {
@ -19,7 +19,7 @@ public class SubScriptSpan extends MetricAffectingSpan {
}
private void apply(TextPaint paint) {
paint.setTextSize(paint.getTextSize() * MarkwonHtmlRendererImpl.SCRIPT_DEF_TEXT_SIZE_RATIO);
paint.setTextSize(paint.getTextSize() * HtmlPlugin.SCRIPT_DEF_TEXT_SIZE_RATIO);
paint.baselineShift -= (int) (paint.ascent() / 2);
}
}

View File

@ -4,7 +4,7 @@ import android.support.annotation.NonNull;
import android.text.TextPaint;
import android.text.style.MetricAffectingSpan;
import ru.noties.markwon.html.MarkwonHtmlRendererImpl;
import ru.noties.markwon.html.HtmlPlugin;
public class SuperScriptSpan extends MetricAffectingSpan {
@ -19,7 +19,7 @@ public class SuperScriptSpan extends MetricAffectingSpan {
}
private void apply(TextPaint paint) {
paint.setTextSize(paint.getTextSize() * MarkwonHtmlRendererImpl.SCRIPT_DEF_TEXT_SIZE_RATIO);
paint.setTextSize(paint.getTextSize() * HtmlPlugin.SCRIPT_DEF_TEXT_SIZE_RATIO);
paint.baselineShift += (int) (paint.ascent() / 2);
}
}

View File

@ -13,12 +13,6 @@ import ru.noties.markwon.html.HtmlTag;
public class HeadingHandler extends SimpleTagHandler {
private final int level;
public HeadingHandler(int level) {
this.level = level;
}
@Nullable
@Override
public Object getSpans(
@ -31,6 +25,18 @@ public class HeadingHandler extends SimpleTagHandler {
return null;
}
int level;
try {
level = Integer.parseInt(tag.name().substring(1));
} catch (NumberFormatException e) {
e.printStackTrace();
level = 0;
}
if (level < 1 || level > 6) {
return null;
}
CoreProps.HEADING_LEVEL.set(renderProps, level);
return factory.getSpans(configuration, renderProps);

View File

@ -9,6 +9,7 @@ import org.commonmark.parser.Parser;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.html.MarkwonHtmlRenderer;
import ru.noties.markwon.image.AsyncDrawableLoader;
import ru.noties.markwon.priority.Priority;
@ -69,6 +70,14 @@ public abstract class AbstractMarkwonPlugin implements MarkwonPlugin {
}
/**
* @inheritDoc
*/
@Override
public void configureHtmlRenderer(@NonNull MarkwonHtmlRenderer.Builder builder) {
}
/**
* @inheritDoc
*/

View File

@ -14,6 +14,7 @@ import java.util.List;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.html.MarkwonHtmlRenderer;
import ru.noties.markwon.image.AsyncDrawableLoader;
import ru.noties.markwon.priority.PriorityProcessor;
@ -102,7 +103,7 @@ class MarkwonBuilderImpl implements Markwon.Builder {
final MarkwonConfiguration.Builder configurationBuilder = new MarkwonConfiguration.Builder();
final MarkwonVisitor.Builder visitorBuilder = new MarkwonVisitorImpl.BuilderImpl();
final MarkwonSpansFactory.Builder spanFactoryBuilder = new MarkwonSpansFactoryImpl.BuilderImpl();
final RenderProps renderProps = new RenderPropsImpl();
final MarkwonHtmlRenderer.Builder htmlRendererBuilder = MarkwonHtmlRenderer.builder();
for (MarkwonPlugin plugin : plugins) {
plugin.configureParser(parserBuilder);
@ -111,13 +112,17 @@ class MarkwonBuilderImpl implements Markwon.Builder {
plugin.configureConfiguration(configurationBuilder);
plugin.configureVisitor(visitorBuilder);
plugin.configureSpansFactory(spanFactoryBuilder);
plugin.configureHtmlRenderer(htmlRendererBuilder);
}
final MarkwonConfiguration configuration = configurationBuilder.build(
themeBuilder.build(),
asyncDrawableLoaderBuilder.build(),
htmlRendererBuilder.build(),
spanFactoryBuilder.build());
final RenderProps renderProps = new RenderPropsImpl();
return new MarkwonImpl(
bufferType,
parserBuilder.build(),

View File

@ -4,6 +4,8 @@ import android.support.annotation.NonNull;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.core.spans.LinkSpan;
import ru.noties.markwon.html.MarkwonHtmlParser;
import ru.noties.markwon.html.MarkwonHtmlRenderer;
import ru.noties.markwon.image.AsyncDrawableLoader;
import ru.noties.markwon.image.ImageSizeResolver;
import ru.noties.markwon.image.ImageSizeResolverDef;
@ -29,6 +31,8 @@ public class MarkwonConfiguration {
private final LinkSpan.Resolver linkResolver;
private final UrlProcessor urlProcessor;
private final ImageSizeResolver imageSizeResolver;
private final MarkwonHtmlParser htmlParser;
private final MarkwonHtmlRenderer htmlRenderer;
// @since 3.0.0
private final MarkwonSpansFactory spansFactory;
@ -41,6 +45,8 @@ public class MarkwonConfiguration {
this.urlProcessor = builder.urlProcessor;
this.imageSizeResolver = builder.imageSizeResolver;
this.spansFactory = builder.spansFactory;
this.htmlParser = builder.htmlParser;
this.htmlRenderer = builder.htmlRenderer;
}
@NonNull
@ -73,6 +79,16 @@ public class MarkwonConfiguration {
return imageSizeResolver;
}
@NonNull
public MarkwonHtmlParser htmlParser() {
return htmlParser;
}
@NonNull
public MarkwonHtmlRenderer htmlRenderer() {
return htmlRenderer;
}
/**
* @since 3.0.0
*/
@ -90,6 +106,8 @@ public class MarkwonConfiguration {
private LinkSpan.Resolver linkResolver;
private UrlProcessor urlProcessor;
private ImageSizeResolver imageSizeResolver;
private MarkwonHtmlParser htmlParser;
private MarkwonHtmlRenderer htmlRenderer;
private MarkwonSpansFactory spansFactory;
Builder() {
@ -113,6 +131,12 @@ public class MarkwonConfiguration {
return this;
}
@NonNull
public Builder htmlParser(@NonNull MarkwonHtmlParser htmlParser) {
this.htmlParser = htmlParser;
return this;
}
/**
* @since 1.0.1
*/
@ -126,10 +150,12 @@ public class MarkwonConfiguration {
public MarkwonConfiguration build(
@NonNull MarkwonTheme theme,
@NonNull AsyncDrawableLoader asyncDrawableLoader,
@NonNull MarkwonHtmlRenderer htmlRenderer,
@NonNull MarkwonSpansFactory spansFactory) {
this.theme = theme;
this.asyncDrawableLoader = asyncDrawableLoader;
this.htmlRenderer = htmlRenderer;
this.spansFactory = spansFactory;
if (syntaxHighlight == null) {
@ -148,6 +174,10 @@ public class MarkwonConfiguration {
imageSizeResolver = new ImageSizeResolverDef();
}
if (htmlParser == null) {
htmlParser = MarkwonHtmlParser.noOp();
}
return new MarkwonConfiguration(this);
}
}

View File

@ -8,6 +8,7 @@ import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.html.MarkwonHtmlRenderer;
import ru.noties.markwon.image.AsyncDrawableLoader;
import ru.noties.markwon.image.MediaDecoder;
import ru.noties.markwon.image.SchemeHandler;
@ -73,7 +74,13 @@ public interface MarkwonPlugin {
*/
void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder);
// can be used to configure own properties and use between plugins
/**
* Configure {@link MarkwonHtmlRenderer} to add or remove HTML {@link ru.noties.markwon.html.TagHandler}s
*
* @see MarkwonHtmlRenderer
* @see MarkwonHtmlRenderer.Builder
*/
void configureHtmlRenderer(@NonNull MarkwonHtmlRenderer.Builder builder);
/**
* A method to store some arbitrary data in {@link RenderProps}. Although it won\'t make

View File

@ -4,15 +4,10 @@ import android.support.annotation.NonNull;
import java.util.Collections;
/**
* @see MarkwonHtmlParser
* @since 2.0.0
*/
class MarkwonHtmlParserNoOp extends MarkwonHtmlParser {
@Override
public <T extends Appendable & CharSequence> void processFragment(@NonNull T output, @NonNull String htmlFragment) {
// no op
}
@Override
@ -27,6 +22,6 @@ class MarkwonHtmlParserNoOp extends MarkwonHtmlParser {
@Override
public void reset() {
// no op
}
}

View File

@ -0,0 +1,65 @@
package ru.noties.markwon.html;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import ru.noties.markwon.MarkwonVisitor;
/**
* @since 2.0.0
*/
public abstract class MarkwonHtmlRenderer {
@NonNull
public static Builder builder() {
return new MarkwonHtmlRendererImpl.BuilderImpl();
}
public abstract void render(
@NonNull MarkwonVisitor visitor,
@NonNull MarkwonHtmlParser parser
);
@Nullable
public abstract TagHandler tagHandler(@NonNull String tagName);
/**
* @since 3.0.0
*/
public interface Builder {
/**
* @param allowNonClosedTags parameter to indicate that all non-closed HTML tags should be
* closed at the end of a document. if {@code true} all non-closed
* tags will be force-closed at the end. Otherwise these tags will be
* ignored and thus not rendered.
* @return self
*/
@NonNull
Builder allowNonClosedTags(boolean allowNonClosedTags);
/**
* Please note that if there is already a {@link TagHandler} registered with specified
* {@code tagName} it will be replaced with newly supplied one.
*
* @param tagHandler {@link TagHandler}
* @param tagName name of a tag
* @return self
*/
@NonNull
Builder addHandler(@NonNull TagHandler tagHandler, @NonNull String tagName);
@NonNull
Builder addHandler(@NonNull TagHandler tagHandler, String... tagNames);
@NonNull
Builder removeHandler(@NonNull String tagName);
@NonNull
Builder removeHandlers(@NonNull String... tagNames);
@NonNull
MarkwonHtmlRenderer build();
}
}

View File

@ -0,0 +1,146 @@
package ru.noties.markwon.html;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ru.noties.markwon.MarkwonVisitor;
class MarkwonHtmlRendererImpl extends MarkwonHtmlRenderer {
private final boolean allowNonClosedTags;
private final Map<String, TagHandler> tagHandlers;
MarkwonHtmlRendererImpl(boolean allowNonClosedTags, @NonNull Map<String, TagHandler> tagHandlers) {
this.allowNonClosedTags = allowNonClosedTags;
this.tagHandlers = tagHandlers;
}
@Override
public void render(
@NonNull final MarkwonVisitor visitor,
@NonNull MarkwonHtmlParser parser) {
final int end;
if (!allowNonClosedTags) {
end = HtmlTag.NO_END;
} else {
end = visitor.length();
}
parser.flushInlineTags(end, new MarkwonHtmlParser.FlushAction<HtmlTag.Inline>() {
@Override
public void apply(@NonNull List<HtmlTag.Inline> tags) {
TagHandler handler;
for (HtmlTag.Inline inline : tags) {
// if tag is not closed -> do not render
if (!inline.isClosed()) {
continue;
}
handler = tagHandler(inline.name());
if (handler != null) {
handler.handle(visitor, MarkwonHtmlRendererImpl.this, inline);
}
}
}
});
parser.flushBlockTags(end, new MarkwonHtmlParser.FlushAction<HtmlTag.Block>() {
@Override
public void apply(@NonNull List<HtmlTag.Block> tags) {
TagHandler handler;
for (HtmlTag.Block block : tags) {
if (!block.isClosed()) {
continue;
}
handler = tagHandler(block.name());
if (handler != null) {
handler.handle(visitor, MarkwonHtmlRendererImpl.this, block);
} 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);
}
static class BuilderImpl implements Builder {
private final Map<String, TagHandler> tagHandlers = new HashMap<>(2);
private boolean allowNonClosedTags;
@NonNull
@Override
public Builder allowNonClosedTags(boolean allowNonClosedTags) {
this.allowNonClosedTags = allowNonClosedTags;
return this;
}
@NonNull
@Override
public Builder addHandler(@NonNull TagHandler tagHandler, @NonNull String tagName) {
tagHandlers.put(tagName, tagHandler);
return this;
}
@NonNull
@Override
public Builder addHandler(@NonNull TagHandler tagHandler, String... tagNames) {
for (String tagName : tagNames) {
if (tagName != null) {
tagHandlers.put(tagName, tagHandler);
}
}
return this;
}
@NonNull
@Override
public Builder removeHandler(@NonNull String tagName) {
tagHandlers.remove(tagName);
return this;
}
@NonNull
@Override
public Builder removeHandlers(@NonNull String... tagNames) {
for (String tagName : tagNames) {
if (tagName != null) {
tagHandlers.remove(tagName);
}
}
return this;
}
@NonNull
@Override
public MarkwonHtmlRenderer build() {
// okay, let's validate that we have at least one tagHandler registered
// if we have none -> return no-op implementation
return tagHandlers.size() > 0
? new MarkwonHtmlRendererImpl(allowNonClosedTags, Collections.unmodifiableMap(tagHandlers))
: new MarkwonHtmlRendererNoOp();
}
}
}

View File

@ -0,0 +1,20 @@
package ru.noties.markwon.html;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import ru.noties.markwon.MarkwonVisitor;
class MarkwonHtmlRendererNoOp extends MarkwonHtmlRenderer {
@Override
public void render(@NonNull MarkwonVisitor visitor, @NonNull MarkwonHtmlParser parser) {
parser.reset();
}
@Nullable
@Override
public TagHandler tagHandler(@NonNull String tagName) {
return null;
}
}

View File

@ -21,6 +21,7 @@ import java.util.List;
import ru.noties.markwon.core.CorePlugin;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.html.MarkwonHtmlRenderer;
import ru.noties.markwon.image.AsyncDrawableLoader;
import ru.noties.markwon.priority.Priority;
import ru.noties.markwon.priority.PriorityProcessor;
@ -216,6 +217,7 @@ public class MarkwonBuilderImplTest {
verify(plugin, times(1)).configureConfiguration(any(MarkwonConfiguration.Builder.class));
verify(plugin, times(1)).configureVisitor(any(MarkwonVisitor.Builder.class));
verify(plugin, times(1)).configureSpansFactory(any(MarkwonSpansFactory.Builder.class));
verify(plugin, times(1)).configureHtmlRenderer(any(MarkwonHtmlRenderer.Builder.class));
// we do not know how many times exactly, but at least once it must be called
verify(plugin, atLeast(1)).priority();

View File

@ -26,6 +26,7 @@ import ru.noties.markwon.SpanFactory;
import ru.noties.markwon.SpannableBuilder;
import ru.noties.markwon.core.CorePluginBridge;
import ru.noties.markwon.core.MarkwonTheme;
import ru.noties.markwon.html.MarkwonHtmlRenderer;
import ru.noties.markwon.image.AsyncDrawableLoader;
import static org.junit.Assert.assertEquals;
@ -83,7 +84,7 @@ public class SyntaxHighlightTest {
final MarkwonConfiguration configuration = MarkwonConfiguration.builder()
.syntaxHighlight(highlight)
.build(mock(MarkwonTheme.class), mock(AsyncDrawableLoader.class), spansFactory);
.build(mock(MarkwonTheme.class), mock(AsyncDrawableLoader.class), mock(MarkwonHtmlRenderer.class), spansFactory);
final Map<Class<? extends Node>, MarkwonVisitor.NodeVisitor<? extends Node>> visitorMap = Collections.emptyMap();